mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #16372 from haukepetersen/opt_nimble_randconnitvl
pkg/nimble/netif: allow to apply and enforce random and unique connection intervals
This commit is contained in:
commit
82409c7551
@ -68,6 +68,7 @@ endif
|
||||
|
||||
ifneq (,$(filter nimble_netif,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += ble_nimble_netif
|
||||
USEMODULE += random
|
||||
USEMODULE += l2util
|
||||
USEMODULE += bluetil_addr
|
||||
ifneq (,$(filter gnrc_ipv6_%,$(USEMODULE)))
|
||||
|
@ -145,8 +145,11 @@ typedef struct {
|
||||
uint32_t scan_win;
|
||||
/** opening a new connection is aborted after this time [in ms] */
|
||||
uint32_t conn_timeout;
|
||||
/** connection interval used when opening a new connection [in ms] */
|
||||
uint32_t conn_itvl;
|
||||
/** connection interval used when opening a new connection, lower bound.
|
||||
* [in ms] */
|
||||
uint32_t conn_itvl_min;
|
||||
/** connection interval, upper bound [in ms] */
|
||||
uint32_t conn_itvl_max;
|
||||
/** slave latency used for new connections [in ms] */
|
||||
uint16_t conn_latency;
|
||||
/** supervision timeout used for new connections [in ms] */
|
||||
|
@ -51,8 +51,11 @@ extern "C" {
|
||||
#ifndef NIMBLE_AUTOCONN_CONN_TIMEOUT_MS
|
||||
#define NIMBLE_AUTOCONN_CONN_TIMEOUT_MS (3 * NIMBLE_AUTOCONN_SCAN_WIN_MS)
|
||||
#endif
|
||||
#ifndef NIMBLE_AUTOCONN_CONN_ITVL_MS
|
||||
#define NIMBLE_AUTOCONN_CONN_ITVL_MS (75U) /* 75ms */
|
||||
#ifndef NIMBLE_AUTOCONN_CONN_ITVL_MIN_MS
|
||||
#define NIMBLE_AUTOCONN_CONN_ITVL_MIN_MS 75U /* 75ms */
|
||||
#endif
|
||||
#ifndef NIMBLE_AUTOCONN_CONN_ITVL_MAX_MS
|
||||
#define NIMBLE_AUTOCONN_CONN_ITVL_MAX_MS 75U /* 75ms */
|
||||
#endif
|
||||
#ifndef NIMBLE_AUTOCONN_CONN_LATENCY
|
||||
#define NIMBLE_AUTOCONN_CONN_LATENCY (0)
|
||||
@ -74,7 +77,8 @@ extern "C" {
|
||||
.scan_itvl = NIMBLE_AUTOCONN_SCAN_ITVL_MS, \
|
||||
.scan_win = NIMBLE_AUTOCONN_SCAN_WIN_MS, \
|
||||
.conn_timeout = NIMBLE_AUTOCONN_CONN_TIMEOUT_MS, \
|
||||
.conn_itvl = NIMBLE_AUTOCONN_CONN_ITVL_MS, \
|
||||
.conn_itvl_min = NIMBLE_AUTOCONN_CONN_ITVL_MIN_MS, \
|
||||
.conn_itvl_max = NIMBLE_AUTOCONN_CONN_ITVL_MAX_MS, \
|
||||
.conn_latency = NIMBLE_AUTOCONN_CONN_LATENCY, \
|
||||
.conn_super_to = NIMBLE_AUTOCONN_CONN_SVTO_MS, \
|
||||
.node_id = NIMBLE_AUTOCONN_NODE_ID, }
|
||||
|
@ -277,8 +277,8 @@ int nimble_autoconn_update(const nimble_autoconn_params_t *params,
|
||||
/* populate the connection parameters */
|
||||
_conn_params.scan_itvl = BLE_GAP_SCAN_ITVL_MS(params->scan_win);
|
||||
_conn_params.scan_window = _conn_params.scan_itvl;
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(params->conn_itvl);
|
||||
_conn_params.itvl_max = _conn_params.itvl_min;
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_min);
|
||||
_conn_params.itvl_max = BLE_GAP_CONN_ITVL_MS(params->conn_itvl_max);
|
||||
_conn_params.latency = 0;
|
||||
_conn_params.supervision_timeout = BLE_GAP_SUPERVISION_TIMEOUT_MS(
|
||||
params->conn_super_to);
|
||||
|
@ -102,6 +102,37 @@ extern "C" {
|
||||
#define NIMBLE_NETIF_MTU (1280U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set to > 0 to enforce different connection intervals for each of the
|
||||
* nodes BLE connections
|
||||
*
|
||||
* Enabling this option will enforce that every BLE connection a node maintains,
|
||||
* independent of the nodes role, uses a different connection interval. The
|
||||
* value of NIMBLE_NETIF_CONN_ITVL_SPACING specifies the minimum spacing between
|
||||
* connection intervals as multiple of 1,25ms. E.g. a value of 2 will force each
|
||||
* connection to use a connection interval that is at least 2.5ms different from
|
||||
* all other used connection intervals.
|
||||
*
|
||||
* If a node is the coordinator of a connection, it will generate a connection
|
||||
* interval for each new connection based on a random value by adhering to the
|
||||
* spacing constraint.
|
||||
*
|
||||
* If a node is the subordinate of a new connection, it will check if the given
|
||||
* connection interval is fulfilling the spacing constraint with respect to
|
||||
* already existing connections of that node. If the connection interval of the
|
||||
* new connection is not properly spaced, the node will drop the connection
|
||||
* right away, giving the coordinator node the possibly to reconnect with a
|
||||
* different connection interval.
|
||||
*/
|
||||
#ifndef NIMBLE_NETIF_CONN_ITVL_SPACING
|
||||
#define NIMBLE_NETIF_CONN_ITVL_SPACING 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Minimum spacing of connection interval when using randomized
|
||||
* intervals, in multiples of 1.25ms
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return codes used by the NimBLE netif module
|
||||
*/
|
||||
@ -183,16 +214,18 @@ void nimble_netif_eventcb(nimble_netif_eventcb_t cb);
|
||||
*
|
||||
* @param[in] addr address of the advertising BLE slave, in the NimBLE
|
||||
* addr format (little endian)
|
||||
* @param[in] conn_params connection (timing) parameters
|
||||
* @param[in] conn_params connection (timing) parameters, set to NULL to use
|
||||
* NimBLEs default parameters
|
||||
* @param[in] timeout connect timeout [in ms]
|
||||
*
|
||||
* @return the used connection handle on success
|
||||
* @return NIMBLE_NETIF_BUSY if already connected to the given address or if
|
||||
* a connection setup procedure is in progress
|
||||
* @return NIMBLE_NETIF_NOMEM if no connection context memory is available
|
||||
* @return NIMBLE_NETIF_NOTFOUND if unable to find valid connection interval
|
||||
*/
|
||||
int nimble_netif_connect(const ble_addr_t *addr,
|
||||
const struct ble_gap_conn_params *conn_params,
|
||||
struct ble_gap_conn_params *conn_params,
|
||||
uint32_t timeout);
|
||||
|
||||
/**
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define NIMBLE_NETIF_CONN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nimble_netif.h"
|
||||
|
||||
@ -175,6 +176,57 @@ int nimble_netif_conn_start_adv(void);
|
||||
*/
|
||||
void nimble_netif_conn_free(int handle, uint8_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Get the used connection interval for the given connection handle
|
||||
*
|
||||
* @param[in] handle connection handle
|
||||
*
|
||||
* @return used connection interval on success, multiples of 1.25ms
|
||||
* @return 0 if unable to get connection interval
|
||||
*/
|
||||
uint16_t nimble_netif_conn_get_itvl(int handle);
|
||||
|
||||
/**
|
||||
* @brief Check if the given connection interval is used, taking the minimal
|
||||
* spacing as defined by NIMBLE_NETIF_CONN_ITVL_SPACING into account
|
||||
*
|
||||
* @param[in] itvl connection interval to check, multiples of 1.25ms
|
||||
* @param[in] skip_handle do not compare against connection interval for this
|
||||
* handle, set to NIMBLE_NETIF_CONN_INVALID to check
|
||||
* all
|
||||
*
|
||||
* @return true if given interval is used
|
||||
* @return false if given interval is not used
|
||||
*/
|
||||
bool nimble_netif_conn_itvl_used(uint16_t itvl, int skip_handle);
|
||||
|
||||
/**
|
||||
* @brief Check if connection interval used by the given connection is valid
|
||||
*
|
||||
* @param[in] handle connection to verify
|
||||
*
|
||||
* @return true if the connection interval of the given connection collides
|
||||
* with the connection interval of another BLE connection
|
||||
* @return false if the connection interval of the given connection is valid
|
||||
*/
|
||||
bool nimble_netif_conn_itvl_invalid(int handle);
|
||||
|
||||
/**
|
||||
* @brief Generate a pseudorandom connection interval from the given range
|
||||
*
|
||||
* If the NIMBLE_NETIF_CONN_ITVL_SPACING option is enabled, this function
|
||||
* ensures that the generated connection interval is spaced at least
|
||||
* NIMBLE_NETIF_CONN_ITVL_SPACING from the connection interval of each open
|
||||
* BLE connection.
|
||||
*
|
||||
* @param[in] min minimum connection interval
|
||||
* @param[in] max maximum connection interval
|
||||
*
|
||||
* @return generated connection interval on success, multiples of 1.25ms
|
||||
* @return 0 if no valid connection interval could be generated
|
||||
*/
|
||||
uint16_t nimble_netif_conn_gen_itvl(uint16_t min, uint16_t max);
|
||||
|
||||
/**
|
||||
* @brief Find the connection context with a given GAP handle and return a
|
||||
* pointer to it
|
||||
|
@ -485,6 +485,11 @@ static int _on_gap_slave_evt(struct ble_gap_event *event, void *arg)
|
||||
_notify(handle, NIMBLE_NETIF_ABORT_SLAVE, addr);
|
||||
break;
|
||||
}
|
||||
if ((NIMBLE_NETIF_CONN_ITVL_SPACING > 0) &&
|
||||
nimble_netif_conn_itvl_invalid(handle)) {
|
||||
nimble_netif_close(handle);
|
||||
break;
|
||||
}
|
||||
_on_gap_connected(conn, event->connect.conn_handle);
|
||||
assert(conn->state == NIMBLE_NETIF_ADV);
|
||||
conn->state = NIMBLE_NETIF_GAP_SLAVE;
|
||||
@ -537,12 +542,15 @@ void nimble_netif_eventcb(nimble_netif_eventcb_t cb)
|
||||
}
|
||||
|
||||
int nimble_netif_connect(const ble_addr_t *addr,
|
||||
const struct ble_gap_conn_params *conn_params,
|
||||
struct ble_gap_conn_params *conn_params,
|
||||
uint32_t timeout)
|
||||
{
|
||||
assert(addr);
|
||||
assert(_eventcb);
|
||||
|
||||
uint16_t itvl_min = 0;
|
||||
uint16_t itvl_max = 0;
|
||||
|
||||
/* the netif_conn module expects addresses in network byte order */
|
||||
uint8_t addrn[BLE_ADDR_LEN];
|
||||
bluetil_addr_swapped_cp(addr->val, addrn);
|
||||
@ -559,11 +567,31 @@ int nimble_netif_connect(const ble_addr_t *addr,
|
||||
return NIMBLE_NETIF_NOMEM;
|
||||
}
|
||||
|
||||
if ((conn_params != NULL)
|
||||
&& (conn_params->itvl_min != conn_params->itvl_max)) {
|
||||
/* we need to save the min/max intervals in order to restore them
|
||||
* later on */
|
||||
itvl_min = conn_params->itvl_min;
|
||||
itvl_max = conn_params->itvl_max;
|
||||
|
||||
uint16_t itvl = nimble_netif_conn_gen_itvl(itvl_min, itvl_max);
|
||||
if (itvl == 0) {
|
||||
return NIMBLE_NETIF_NOTFOUND;
|
||||
}
|
||||
conn_params->itvl_min = itvl;
|
||||
conn_params->itvl_max = itvl;
|
||||
}
|
||||
|
||||
int res = ble_gap_connect(nimble_riot_own_addr_type, addr, timeout,
|
||||
conn_params, _on_gap_master_evt, (void *)handle);
|
||||
assert(res == 0);
|
||||
(void)res;
|
||||
|
||||
if (itvl_min != itvl_max) {
|
||||
conn_params->itvl_min = itvl_min;
|
||||
conn_params->itvl_max = itvl_max;
|
||||
}
|
||||
|
||||
_notify(handle, NIMBLE_NETIF_INIT_MASTER, addrn);
|
||||
|
||||
return handle;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "nimble_netif_conn.h"
|
||||
#include "random.h"
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
@ -220,3 +221,77 @@ unsigned nimble_netif_conn_count(uint16_t filter)
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
uint16_t nimble_netif_conn_get_itvl(int handle)
|
||||
{
|
||||
assert((handle >= 0) && (handle < CONN_CNT));
|
||||
struct ble_gap_conn_desc desc;
|
||||
|
||||
if (!(_conn[handle].state & NIMBLE_NETIF_GAP_CONNECTED)) {
|
||||
return 0;
|
||||
}
|
||||
int res = ble_gap_conn_find(_conn[handle].gaphandle, &desc);
|
||||
if (res != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return desc.conn_itvl;
|
||||
}
|
||||
|
||||
bool nimble_netif_conn_itvl_used(uint16_t itvl, int skip_handle)
|
||||
{
|
||||
for (unsigned i = 0; i < CONN_CNT; i++) {
|
||||
if (i != skip_handle) {
|
||||
uint16_t conn_itvl = nimble_netif_conn_get_itvl(i);
|
||||
if (conn_itvl != 0) {
|
||||
uint16_t diff = (conn_itvl < itvl) ? itvl - conn_itvl
|
||||
: conn_itvl - itvl;
|
||||
if (diff < NIMBLE_NETIF_CONN_ITVL_SPACING) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool nimble_netif_conn_itvl_invalid(int handle)
|
||||
{
|
||||
if (NIMBLE_NETIF_CONN_ITVL_SPACING == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t to_check = nimble_netif_conn_get_itvl(handle);
|
||||
if (to_check == 0) {
|
||||
return false;
|
||||
}
|
||||
return nimble_netif_conn_itvl_used(to_check, handle);
|
||||
}
|
||||
|
||||
uint16_t nimble_netif_conn_gen_itvl(uint16_t min, uint16_t max)
|
||||
{
|
||||
assert(min <= max);
|
||||
|
||||
uint16_t start = random_uint32_range(min, max);
|
||||
|
||||
if (NIMBLE_NETIF_CONN_ITVL_SPACING == 0) {
|
||||
return start;
|
||||
}
|
||||
|
||||
for (uint16_t itvl = start;
|
||||
itvl <= max;
|
||||
itvl += NIMBLE_NETIF_CONN_ITVL_SPACING) {
|
||||
if (!nimble_netif_conn_itvl_used(itvl, NIMBLE_NETIF_CONN_INVALID)) {
|
||||
return itvl;
|
||||
}
|
||||
}
|
||||
for (uint16_t itvl = start - NIMBLE_NETIF_CONN_ITVL_SPACING;
|
||||
itvl >= min;
|
||||
itvl -= NIMBLE_NETIF_CONN_ITVL_SPACING) {
|
||||
if (!nimble_netif_conn_itvl_used(itvl, NIMBLE_NETIF_CONN_INVALID)) {
|
||||
return itvl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,14 +27,10 @@
|
||||
|
||||
#include "host/ble_hs.h"
|
||||
|
||||
#if NIMBLE_STATCONN_CONN_ITVL_MIN_MS != NIMBLE_STATCONN_CONN_ITVL_MAX_MS
|
||||
#include "random.h"
|
||||
|
||||
/* sanity check on the conn interval range to catch configuration errors */
|
||||
#if NIMBLE_STATCONN_CONN_ITVL_MIN_MS > NIMBLE_STATCONN_CONN_ITVL_MAX_MS
|
||||
#error "nimble_statconn: CONN_ITVL_MIN_MS must be <= CONN_ITVL_MAX_MS"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ENABLE_DEBUG 0
|
||||
#include "debug.h"
|
||||
@ -91,16 +87,6 @@ static void _activate(uint8_t role)
|
||||
ble_addr_t peer;
|
||||
peer.type = BLE_ADDR_RANDOM;
|
||||
bluetil_addr_swapped_cp(slot->addr, peer.val);
|
||||
/* compute a random new random connection interval if configured */
|
||||
#if NIMBLE_STATCONN_CONN_ITVL_MIN_MS != NIMBLE_STATCONN_CONN_ITVL_MAX_MS
|
||||
uint32_t itvl = random_uint32_range(NIMBLE_STATCONN_CONN_ITVL_MIN_MS,
|
||||
NIMBLE_STATCONN_CONN_ITVL_MAX_MS);
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(itvl);
|
||||
#else
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(
|
||||
NIMBLE_STATCONN_CONN_ITVL_MIN_MS);
|
||||
#endif
|
||||
_conn_params.itvl_max = _conn_params.itvl_min;
|
||||
/* try to (re)open the connection */
|
||||
nimble_netif_connect(&peer, &_conn_params, _conn_timeout);
|
||||
}
|
||||
@ -208,6 +194,10 @@ void nimble_statconn_init(void)
|
||||
_conn_params.latency = NIMBLE_STATCONN_CONN_LATENCY;
|
||||
_conn_params.supervision_timeout = BLE_GAP_SUPERVISION_TIMEOUT_MS(
|
||||
NIMBLE_STATCONN_CONN_SUPERTO_MS);
|
||||
_conn_params.itvl_min = BLE_GAP_CONN_ITVL_MS(
|
||||
NIMBLE_STATCONN_CONN_ITVL_MIN_MS);
|
||||
_conn_params.itvl_max = BLE_GAP_CONN_ITVL_MS(
|
||||
NIMBLE_STATCONN_CONN_ITVL_MAX_MS);
|
||||
_conn_params.min_ce_len = 0;
|
||||
_conn_params.max_ce_len = 0;
|
||||
_conn_timeout = NIMBLE_STATCONN_CONN_TIMEOUT_MS;
|
||||
|
Loading…
Reference in New Issue
Block a user