mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
pkg/nimble/netif: use random connection intervals
This commit is contained in:
parent
4d6d46534d
commit
402bd20ec9
@ -68,6 +68,7 @@ endif
|
|||||||
|
|
||||||
ifneq (,$(filter nimble_netif,$(USEMODULE)))
|
ifneq (,$(filter nimble_netif,$(USEMODULE)))
|
||||||
FEATURES_REQUIRED += ble_nimble_netif
|
FEATURES_REQUIRED += ble_nimble_netif
|
||||||
|
USEMODULE += random
|
||||||
USEMODULE += l2util
|
USEMODULE += l2util
|
||||||
USEMODULE += bluetil_addr
|
USEMODULE += bluetil_addr
|
||||||
ifneq (,$(filter gnrc_ipv6_%,$(USEMODULE)))
|
ifneq (,$(filter gnrc_ipv6_%,$(USEMODULE)))
|
||||||
|
@ -102,6 +102,37 @@ extern "C" {
|
|||||||
#define NIMBLE_NETIF_MTU (1280U)
|
#define NIMBLE_NETIF_MTU (1280U)
|
||||||
#endif
|
#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
|
* @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
|
* @param[in] addr address of the advertising BLE slave, in the NimBLE
|
||||||
* addr format (little endian)
|
* 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]
|
* @param[in] timeout connect timeout [in ms]
|
||||||
*
|
*
|
||||||
* @return the used connection handle on success
|
* @return the used connection handle on success
|
||||||
* @return NIMBLE_NETIF_BUSY if already connected to the given address or if
|
* @return NIMBLE_NETIF_BUSY if already connected to the given address or if
|
||||||
* a connection setup procedure is in progress
|
* a connection setup procedure is in progress
|
||||||
* @return NIMBLE_NETIF_NOMEM if no connection context memory is available
|
* @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,
|
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);
|
uint32_t timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define NIMBLE_NETIF_CONN_H
|
#define NIMBLE_NETIF_CONN_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "nimble_netif.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);
|
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
|
* @brief Find the connection context with a given GAP handle and return a
|
||||||
* pointer to it
|
* 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);
|
_notify(handle, NIMBLE_NETIF_ABORT_SLAVE, addr);
|
||||||
break;
|
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);
|
_on_gap_connected(conn, event->connect.conn_handle);
|
||||||
assert(conn->state == NIMBLE_NETIF_ADV);
|
assert(conn->state == NIMBLE_NETIF_ADV);
|
||||||
conn->state = NIMBLE_NETIF_GAP_SLAVE;
|
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,
|
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)
|
uint32_t timeout)
|
||||||
{
|
{
|
||||||
assert(addr);
|
assert(addr);
|
||||||
assert(_eventcb);
|
assert(_eventcb);
|
||||||
|
|
||||||
|
uint16_t itvl_min = 0;
|
||||||
|
uint16_t itvl_max = 0;
|
||||||
|
|
||||||
/* the netif_conn module expects addresses in network byte order */
|
/* the netif_conn module expects addresses in network byte order */
|
||||||
uint8_t addrn[BLE_ADDR_LEN];
|
uint8_t addrn[BLE_ADDR_LEN];
|
||||||
bluetil_addr_swapped_cp(addr->val, addrn);
|
bluetil_addr_swapped_cp(addr->val, addrn);
|
||||||
@ -559,11 +567,31 @@ int nimble_netif_connect(const ble_addr_t *addr,
|
|||||||
return NIMBLE_NETIF_NOMEM;
|
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,
|
int res = ble_gap_connect(nimble_riot_own_addr_type, addr, timeout,
|
||||||
conn_params, _on_gap_master_evt, (void *)handle);
|
conn_params, _on_gap_master_evt, (void *)handle);
|
||||||
assert(res == 0);
|
assert(res == 0);
|
||||||
(void)res;
|
(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);
|
_notify(handle, NIMBLE_NETIF_INIT_MASTER, addrn);
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "nimble_netif_conn.h"
|
#include "nimble_netif_conn.h"
|
||||||
|
#include "random.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG 0
|
#define ENABLE_DEBUG 0
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -220,3 +221,77 @@ unsigned nimble_netif_conn_count(uint16_t filter)
|
|||||||
|
|
||||||
return cnt;
|
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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user