nimble/ll: Decouple aux scanner from main scansm

This change moves handling of scanning aux PDUs to separate unit and
thus simplifies code in ble_ll_scan. Basically, once ADV_EXT_IND is
scanned by main scansm, scanning aux PDUs is running as a separate
LL state and is handled by separate code.

Handling on aux PDUs was also refactored a bit, more importantly we
no longer need ref/unref for aux_data which caused lots of issues in
the past - aux_data is always only allocated in ISR context when
ADV_EXT_IND with AuxPtr is received and then can be freed only in
LL context if no subsequent scan is scheduled.

In addition, some changes were done to filtering routines so that now
filtering and address resolution is done only once for each scanned
ext advertising event, i.e. either on ADV_EXT_IND or AUX_ADV_IND.

There is still some legacy code for aux scanner left since it's used
by initiator role. This will be eventually removed once initiator is
refactored to use the same code as generic scanner.
This commit is contained in:
Andrzej Kaczmarek
2021-09-30 12:14:23 +02:00
parent e084ef70ef
commit eed4389851
12 changed files with 1961 additions and 930 deletions
@@ -220,6 +220,7 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
#define BLE_LL_STATE_CONNECTION (4)
#define BLE_LL_STATE_DTM (5)
#define BLE_LL_STATE_SYNC (6)
#define BLE_LL_STATE_SCAN_AUX (7)
/* LL Features */
#define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001)
@@ -354,6 +355,7 @@ struct ble_dev_addr
#define BLE_LL_EXT_ADV_FLAGS_SIZE (1)
#define BLE_LL_EXT_ADV_ADVA_SIZE (6)
#define BLE_LL_EXT_ADV_TARGETA_SIZE (6)
#define BLE_LL_EXT_ADV_CTE_INFO_SIZE (1)
#define BLE_LL_EXT_ADV_DATA_INFO_SIZE (2)
#define BLE_LL_EXT_ADV_AUX_PTR_SIZE (3)
#define BLE_LL_EXT_ADV_SYNC_INFO_SIZE (18)
@@ -72,6 +72,12 @@ int ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len,
struct ble_ll_resolv_entry *
ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type);
static inline int8_t
ble_ll_resolv_get_idx(struct ble_ll_resolv_entry *rl)
{
return rl - g_ble_ll_resolv_list;
}
/* Returns true if address resolution is enabled */
uint8_t ble_ll_resolv_enabled(void);
@@ -149,6 +149,20 @@ struct ble_ll_scan_pdu_data {
uint8_t adva[BLE_DEV_ADDR_LEN];
};
struct ble_ll_scan_addr_data {
uint8_t *adva;
uint8_t *targeta;
uint8_t *adv_addr;
uint8_t adva_type : 1;
uint8_t targeta_type : 1;
uint8_t adv_addr_type : 1;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
uint8_t adva_resolved : 1;
uint8_t targeta_resolved : 1;
int8_t rpa_index;
#endif
};
struct ble_ll_scan_sm
{
uint8_t scan_enabled;
@@ -286,6 +300,25 @@ void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
/* Called to halt currently running scan */
void ble_ll_scan_halt(void);
uint8_t *ble_ll_get_scan_nrpa(void);
uint8_t ble_ll_scan_get_own_addr_type(void);
uint8_t ble_ll_scan_get_filt_policy(void);
uint8_t ble_ll_scan_get_filt_dups(void);
uint8_t ble_ll_scan_backoff_kick(void);
void ble_ll_scan_backoff_update(int success);
int ble_ll_scan_dup_check_ext(uint8_t addr_type, uint8_t *addr, bool has_aux,
uint16_t adi);
int ble_ll_scan_dup_update_ext(uint8_t addr_type, uint8_t *addr, bool has_aux,
uint16_t adi);
int ble_ll_scan_have_rxd_scan_rsp(uint8_t *addr, uint8_t txadd, uint8_t ext_adv,
uint16_t adi);
void ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, uint8_t ext_adv,
uint16_t adi);
int ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy,
struct ble_ll_scan_addr_data *addrd, uint8_t *scan_ok);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef H_BLE_LL_SCAN_AUX_
#define H_BLE_LL_SCAN_AUX_
#ifdef __cplusplus
extern "C" {
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
struct ble_ll_scan_aux_data;
void ble_ll_scan_aux_init(void);
int ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_time,
uint8_t pdu_time_rem, uint32_t aux_ptr);
int ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr);
int ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok);
void ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr);
void ble_ll_scan_aux_break(struct ble_ll_scan_aux_data *aux);
void ble_ll_scan_aux_wfr_timer_exp(void);
void ble_ll_scan_aux_halt(void);
void ble_ll_scan_aux_sched_remove(struct ble_ll_sched_item *sch);
int ble_ll_scan_aux_rx_isr_end_on_ext(struct ble_ll_scan_sm *scansm,
struct os_mbuf *rxpdu);
void ble_ll_scan_aux_pkt_in_on_ext(struct os_mbuf *rxpdu,
struct ble_mbuf_hdr *rxhdr);
#endif
#ifdef __cplusplus
}
#endif
#endif /* H_BLE_LL_SCAN_AUX_ */
@@ -71,6 +71,7 @@ extern uint8_t g_ble_ll_sched_offset_ticks;
#define BLE_LL_SCHED_TYPE_DTM (5)
#define BLE_LL_SCHED_TYPE_PERIODIC (6)
#define BLE_LL_SCHED_TYPE_SYNC (7)
#define BLE_LL_SCHED_TYPE_SCAN_AUX (8)
/* Return values for schedule callback. */
#define BLE_LL_SCHED_STATE_RUNNING (0)
@@ -200,6 +201,9 @@ int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
struct ble_ll_aux_data *aux_scan);
int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode);
int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time,
uint8_t pdu_time_rem, uint32_t offset_us);
#endif
/* Stop the scheduler */
@@ -30,6 +30,7 @@
extern "C" {
#endif
struct ble_ll_scan_addr_data;
struct ble_ll_sync_sm;
int ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len);
@@ -48,8 +49,7 @@ void ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
uint16_t max_skip, uint32_t sync_timeout);
void ble_ll_sync_transfer_disconnected(struct ble_ll_conn_sm *connsm);
void ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type,
int rpa_index, uint8_t sid,
void ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd, uint8_t sid,
struct ble_mbuf_hdr *rxhdr,
const uint8_t *syncinfo);
+27
View File
@@ -37,6 +37,7 @@
#include "controller/ble_ll_adv.h"
#include "controller/ble_ll_sched.h"
#include "controller/ble_ll_scan.h"
#include "controller/ble_ll_scan_aux.h"
#include "controller/ble_ll_hci.h"
#include "controller/ble_ll_whitelist.h"
#include "controller/ble_ll_resolv.h"
@@ -688,6 +689,11 @@ ble_ll_wfr_timer_exp(void *arg)
case BLE_LL_STATE_SYNC:
ble_ll_sync_wfr_timer_exp();
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_LL_STATE_SCAN_AUX:
ble_ll_scan_aux_wfr_timer_exp();
break;
#endif
default:
break;
@@ -848,6 +854,11 @@ ble_ll_rx_pkt_in(void)
case BLE_LL_STATE_SYNC:
ble_ll_sync_rx_pkt_in(m, ble_hdr);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_LL_STATE_SCAN_AUX:
ble_ll_scan_aux_rx_pkt_in(m, ble_hdr);
break;
#endif
default:
/* Any other state should never occur */
@@ -984,6 +995,11 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr)
case BLE_LL_STATE_SYNC:
rc = ble_ll_sync_rx_isr_start(pdu_type, rxhdr);
break;
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_LL_STATE_SCAN_AUX:
rc = ble_ll_scan_aux_rx_isr_start(pdu_type, rxhdr);
break;
#endif
default:
/* Should not be in this state! */
@@ -1109,6 +1125,17 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
case BLE_LL_STATE_INITIATING:
rc = ble_ll_init_rx_isr_end(rxbuf, crcok, rxhdr);
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_LL_STATE_SCAN_AUX:
if (!badpkt) {
rxpdu = ble_ll_rxpdu_alloc(len + BLE_LL_PDU_HDR_LEN);
if (rxpdu) {
ble_phy_rxpdu_copy(rxbuf, rxpdu);
}
}
rc = ble_ll_scan_aux_rx_isr_end(rxpdu, crcok);
break;
#endif
default:
rc = -1;
STATS_INC(ble_ll_stats, bad_ll_state);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+68
View File
@@ -28,6 +28,7 @@
#include "controller/ble_ll_sched.h"
#include "controller/ble_ll_adv.h"
#include "controller/ble_ll_scan.h"
#include "controller/ble_ll_scan_aux.h"
#include "controller/ble_ll_rfmgmt.h"
#include "controller/ble_ll_trace.h"
#include "controller/ble_ll_sync.h"
@@ -244,6 +245,9 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
ble_ll_adv_event_rmvd_from_sched((struct ble_ll_adv_sm *)entry->cb_arg);
break;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
case BLE_LL_SCHED_TYPE_SCAN_AUX:
ble_ll_scan_aux_break(entry->cb_arg);
break;
case BLE_LL_SCHED_TYPE_AUX_SCAN:
ble_ll_scan_end_adv_evt((struct ble_ll_aux_data *)entry->cb_arg);
break;
@@ -1463,6 +1467,11 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch)
} else if (lls == BLE_LL_STATE_SYNC) {
STATS_INC(ble_ll_stats, sched_state_sync_errs);
ble_ll_sync_halt();
#endif
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
} else if (lls == BLE_LL_STATE_SCAN_AUX) {
ble_ll_state_set(BLE_LL_STATE_STANDBY);
ble_ll_scan_aux_halt();
#endif
} else {
STATS_INC(ble_ll_stats, sched_state_conn_errs);
@@ -1714,6 +1723,65 @@ done:
return rc;
}
int
ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time,
uint8_t pdu_time_rem, uint32_t offset_us)
{
struct ble_ll_sched_item *entry;
uint32_t offset_ticks;
os_sr_t sr;
int rc;
offset_us += pdu_time_rem;
offset_ticks = os_cputime_usecs_to_ticks(offset_us);
sch->start_time = pdu_time + offset_ticks - g_ble_ll_sched_offset_ticks;
sch->remainder = offset_us - os_cputime_ticks_to_usecs(offset_ticks);
/* TODO: make some sane slot reservation */
sch->end_time = sch->start_time + os_cputime_usecs_to_ticks(5000);
OS_ENTER_CRITICAL(sr);
if (!ble_ll_sched_insert_if_empty(sch)) {
/* Scheduler was empty, inserted as 1st element */
rc = 0;
goto done;
}
os_cputime_timer_stop(&g_ble_ll_sched_timer);
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
if (CPUTIME_LEQ(sch->end_time, entry->start_time)) {
TAILQ_INSERT_BEFORE(entry, sch, link);
sch->enqueued = 1;
rc = 0;
break;
}
if (ble_ll_sched_is_overlap(sch, entry)) {
rc = -1;
break;
}
}
if (!entry) {
TAILQ_INSERT_TAIL(&g_ble_ll_sched_q, sch, link);
sch->enqueued = 1;
rc = 0;
}
done:
entry = TAILQ_FIRST(&g_ble_ll_sched_q);
OS_EXIT_CRITICAL(sr);
if (entry == sch) {
ble_ll_rfmgmt_sched_changed(sch);
}
os_cputime_timer_start(&g_ble_ll_sched_timer, entry->start_time);
return rc;
}
#endif
#if MYNEWT_VAL(BLE_LL_DTM)
+12 -20
View File
@@ -1333,14 +1333,11 @@ ble_ll_sync_event_end(struct ble_npl_event *ev)
}
void
ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, int rpa_index,
ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd,
uint8_t sid, struct ble_mbuf_hdr *rxhdr,
const uint8_t *syncinfo)
{
struct ble_ll_sync_sm *sm = NULL;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
const uint8_t *rpa = NULL;
#endif
uint16_t max_skip;
uint32_t offset;
uint32_t usecs;
@@ -1365,28 +1362,21 @@ ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, int rpa_index,
return;
}
/* check if resolved */
if (rpa_index >= 0) {
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
rpa = addr;
#endif
addr = g_ble_ll_resolv_list[rpa_index].rl_identity_addr;
addr_type = g_ble_ll_resolv_list[rpa_index].rl_addr_type;
}
/* check peer */
if (g_ble_ll_sync_create_params.options & BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER) {
if (ble_ll_sync_on_list(addr, addr_type, sid) < 0) {
if (ble_ll_sync_on_list(addrd->adv_addr,
addrd->adv_addr_type, sid) < 0) {
return;
}
/* set addr and sid in sm */
sm->adv_sid = sid;
sm->adv_addr_type = addr_type;
memcpy(sm->adv_addr, addr, BLE_DEV_ADDR_LEN);
sm->adv_addr_type = addrd->adv_addr_type;
memcpy(sm->adv_addr, addrd->adv_addr, BLE_DEV_ADDR_LEN);
} else {
if ((sm->adv_sid != sid) || (sm->adv_addr_type != addr_type) ||
memcmp(sm->adv_addr, addr, BLE_DEV_ADDR_LEN)) {
if ((sm->adv_sid != sid) ||
(sm->adv_addr_type != addrd->adv_addr_type) ||
memcmp(sm->adv_addr, addrd->adv_addr, BLE_DEV_ADDR_LEN)) {
return;
}
}
@@ -1406,12 +1396,14 @@ ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type, int rpa_index,
return;
}
if (rpa_index >= 0) {
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
if (addrd->adva_resolved) {
sm->flags |= BLE_LL_SYNC_SM_FLAG_ADDR_RESOLVED;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
memcpy(sm->adv_addr_rpa, rpa, BLE_DEV_ADDR_LEN);
memcpy(sm->adv_addr_rpa, addrd->adva, BLE_DEV_ADDR_LEN);
#endif
}
#endif
/* set params from HCI LE Create Periodic Sync */
sm->timeout = g_ble_ll_sync_create_params.timeout;
+6
View File
@@ -291,6 +291,12 @@ syscfg.defs:
restrictions:
- 'BLE_LL_CFG_FEAT_LL_ISO if 1'
BLE_LL_SCAN_AUX_SEGMENT_CNT:
description: >
Number of auxiliary advertising segments that can be scanned
concurrently (Core 5.2, Vol 6, Part B, 4.4.2.2.2).
value: 8
BLE_LL_EXT_ADV_AUX_PTR_CNT:
description: >
This option configure a max number of scheduled outstanding auxiliary