1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pkg/nimble/netif: fix randomized conn intervals

This commit is contained in:
Hauke Petersen 2021-07-01 09:36:32 +02:00
parent c5a1012695
commit 46f6bf1987
3 changed files with 41 additions and 54 deletions

View File

@ -42,6 +42,7 @@ extern "C" {
typedef struct {
struct ble_l2cap_chan *coc; /**< l2cap context as exposed by NimBLE */
uint16_t gaphandle; /**< GAP handle exposed by NimBLE */
uint16_t itvl; /**< currently used connection interval */
uint16_t state; /**< the current state of the context */
uint8_t addr[BLE_ADDR_LEN]; /**< BLE address of connected peer
(in network byte order) */
@ -181,10 +182,10 @@ void nimble_netif_conn_free(int handle, uint8_t *addr);
*
* @param[in] handle connection handle
*
* @return used connection interval on success, multiples of 1.25ms
* @return used connection interval in milliseconds on success
* @return 0 if unable to get connection interval
*/
uint16_t nimble_netif_conn_get_itvl(int handle);
uint16_t nimble_netif_conn_get_itvl_ms(int handle);
/**
* @brief Check if the given connection interval is used, taking the minimal
@ -200,17 +201,6 @@ uint16_t nimble_netif_conn_get_itvl(int handle);
*/
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
*

View File

@ -364,20 +364,32 @@ static int _on_l2cap_server_evt(struct ble_l2cap_event *event, void *arg)
conn = nimble_netif_conn_get(handle);
assert(conn);
/* in the unlikely event the L2CAP connection establishment fails,
* we close the GAP connection */
if (event->connect.status != 0) {
/* in the unlikely event the L2CAP connection establishment
* fails, we close the GAP connection */
ble_gap_terminate(conn->gaphandle, BLE_ERR_REM_USER_CONN_TERM);
break;
}
/* we need to update the state to keep everything in sync */
conn->coc = event->connect.chan;
conn->state |= NIMBLE_NETIF_L2CAP_SERVER;
conn->state &= ~(NIMBLE_NETIF_ADV | NIMBLE_NETIF_CONNECTING);
/* in case conn itvl spacing is enabled, make sure that the conn
* itvl of the new connection is sufficiently spaced */
if ((NIMBLE_NETIF_CONN_ITVL_SPACING > 0) &&
nimble_netif_conn_itvl_used(conn->itvl, handle)) {
ble_gap_terminate(conn->gaphandle, BLE_ERR_REM_USER_CONN_TERM);
break;
}
_notify(handle, NIMBLE_NETIF_CONNECTED_SLAVE, conn->addr);
break;
case BLE_L2CAP_EVENT_COC_DISCONNECTED:
conn = nimble_netif_conn_from_gaphandle(event->disconnect.conn_handle);
assert(conn && (conn->state & NIMBLE_NETIF_L2CAP_SERVER));
conn->coc = NULL;
conn->state &= ~NIMBLE_NETIF_L2CAP_CONNECTED;
break;
case BLE_L2CAP_EVENT_COC_ACCEPT: {
@ -411,9 +423,21 @@ static void _on_gap_connected(nimble_netif_conn_t *conn, uint16_t conn_handle)
(void)res;
conn->gaphandle = conn_handle;
conn->itvl = desc.conn_itvl;
bluetil_addr_swapped_cp(desc.peer_id_addr.val, conn->addr);
}
static void _on_gap_param_update(int handle, nimble_netif_conn_t *conn)
{
struct ble_gap_conn_desc desc;
int res = ble_gap_conn_find(conn->gaphandle, &desc);
assert(res == 0) ;
(void)res;
conn->itvl = desc.conn_itvl;
_notify(handle, NIMBLE_NETIF_CONN_UPDATED, conn->addr);
}
static int _on_gap_master_evt(struct ble_gap_event *event, void *arg)
{
int res = 0;
@ -458,7 +482,7 @@ static int _on_gap_master_evt(struct ble_gap_event *event, void *arg)
break;
}
case BLE_GAP_EVENT_CONN_UPDATE:
_notify(handle, NIMBLE_NETIF_CONN_UPDATED, conn->addr);
_on_gap_param_update(handle, conn);
break;
case BLE_GAP_EVENT_CONN_UPDATE_REQ:
case BLE_GAP_EVENT_MTU:
@ -485,11 +509,6 @@ 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;
@ -507,7 +526,7 @@ static int _on_gap_slave_evt(struct ble_gap_event *event, void *arg)
break;
}
case BLE_GAP_EVENT_CONN_UPDATE:
_notify(handle, NIMBLE_NETIF_CONN_UPDATED, conn->addr);
_on_gap_param_update(handle, conn);
break;
case BLE_GAP_EVENT_CONN_UPDATE_REQ:
/* nothing to do here */

View File

@ -222,33 +222,24 @@ unsigned nimble_netif_conn_count(uint16_t filter)
return cnt;
}
uint16_t nimble_netif_conn_get_itvl(int handle)
uint16_t nimble_netif_conn_get_itvl_ms(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) {
if ((handle == 0) || (handle >= CONN_CNT)) {
return 0;
}
return desc.conn_itvl;
return ((_conn[handle].itvl * BLE_HCI_CONN_ITVL) / 1000);
}
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;
}
for (int handle = 0; handle < CONN_CNT; handle++) {
if ((handle != skip_handle) && (_conn[handle].itvl != 0)) {
uint16_t diff = (_conn[handle].itvl < itvl)
? itvl - _conn[handle].itvl
: _conn[handle].itvl - itvl;
if (diff < NIMBLE_NETIF_CONN_ITVL_SPACING) {
return true;
}
}
}
@ -256,19 +247,6 @@ bool nimble_netif_conn_itvl_used(uint16_t itvl, int skip_handle)
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);