Skip to content

Commit

Permalink
Merge pull request #16364 from haukepetersen/add_nimble_rpble_pr
Browse files Browse the repository at this point in the history
net/BLE: add support for RPL-over-BLE
  • Loading branch information
miri64 authored Aug 24, 2021
2 parents 16f7c94 + f24e3ff commit be61154
Show file tree
Hide file tree
Showing 14 changed files with 823 additions and 0 deletions.
3 changes: 3 additions & 0 deletions pkg/nimble/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ nimble_autoconn:
nimble_netif:
$(QQ)"$(MAKE)" -C $(TDIR)/netif/

nimble_rpble:
$(QQ)"$(MAKE)" -C $(TDIR)/rpble/

nimble_scanlist:
$(QQ)"$(MAKE)" -C $(TDIR)/scanlist

Expand Down
7 changes: 7 additions & 0 deletions pkg/nimble/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ ifneq (,$(filter nimble_autoconn,$(USEMODULE)))
USEMODULE += bluetil_ad
endif

ifneq (,$(filter nimble_rpble,$(USEMODULE)))
USEMODULE += gnrc_rpl
USEMODULE += nimble_netif
USEMODULE += nimble_scanner
USEMODULE += bluetil_ad
endif

ifneq (,$(filter nimble_scanlist,$(USEMODULE)))
USEMODULE += nimble_addr
USEMODULE += bluetil_ad
Expand Down
3 changes: 3 additions & 0 deletions pkg/nimble/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ ifneq (,$(filter nimble_netif,$(USEMODULE)))
CFLAGS += -DMYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT=1
endif
endif
ifneq (,$(filter nimble_rpble,$(USEMODULE)))
INCLUDES += -I$(RIOTPKG)/nimble/rpble/include
endif
ifneq (,$(filter nimble_scanlist,$(USEMODULE)))
INCLUDES += -I$(RIOTPKG)/nimble/scanlist/include
endif
Expand Down
10 changes: 10 additions & 0 deletions pkg/nimble/contrib/nimble_riot.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
#endif
#include "controller/ble_ll.h"

#ifdef MODULE_NIMBLE_RPBLE
#include "nimble_rpble.h"
#include "nimble_rpble_params.h"
#endif

static char _stack_controller[NIMBLE_CONTROLLER_STACKSIZE];
#endif

Expand Down Expand Up @@ -160,4 +165,9 @@ void nimble_riot_init(void)
extern void nimble_autoadv_init(void);
nimble_autoadv_init();
#endif

#ifdef MODULE_NIMBLE_RPBLE
res = nimble_rpble_init(&nimble_rpble_params);
assert(res == 0);
#endif
}
3 changes: 3 additions & 0 deletions pkg/nimble/rpble/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE = nimble_rpble

include $(RIOTBASE)/Makefile.base
181 changes: 181 additions & 0 deletions pkg/nimble/rpble/include/nimble_rpble.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Copyright (C) 2019-2021 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @defgroup pkg_nimble_rpble RPL-over-BLE for NimBLE
* @ingroup pkg_nimble
* @brief RPL-over-BLE for Nimble implementation
*
* # About
* This module implements a BLE connection manager the manages BLE connections
* for (multi-hop) IP over BLE networks based on meta data provided by RPL.
*
*
* # Concept
* In their initial state, after power up or reboot, nodes start to scan for
* BLE advertisements containing a specific advertising data (AD) field which
* holds information about RPL DODAGs. For a configured amount of time, the node
* ranks all senders of the received advertising packets based on a given
* metric. After this time, the node selects the best fitting parent based on
* this ranking and tries to connect to that peer.
*
* After a node has successfully opened a connection to its parent node, the
* node starts to advertise its own RPL context data to accept connections
* from potential child nodes.
*
* This approach leads to a BLE network topology that is equal to the IP routing
* topology created by RPL on top.
*
* ## Advertising data structure
* To include RPL context information into (legacy) BLE advertisements, it must
* be encoded into the BLE advertising data format. This implementation uses
* a custom sub-format that is included into the 16-bit UUID Service Data
* (type: 0x16) field (Supplement to Bluetooth Core Specification CSSv8, 1.11).
* The 16-bit UUID in this field is set to the IPSS service ID (0x1820).
*
* The following sub-format is used to encode the RPL context data:
* ```
* byte 1: instance ID (1b)
* byte 2-17: DODAG ID (16b)
* byte 18: DODAG version (1b)
* byte 19: RPL role (1b)
* byte 20-21: rank (2b)
* byte 22: number of free BLE connection slots (1b)
* ```
*
* ## Ranking of potential parents
* The currently implemented ranking metric is very simple: the potential parent
* node with the smallest rank is chosen. Additionally, nodes advertise the
* number of free BLE connection slots. In case where multiple nodes advertise
* the same RPL rank, the one with the largest number of open BLE connection
* slots is selected. The idea behind this is to balance the number of BLE
* connections per node, and with that also to balance the RPL DODAG.
*
*
* # Usage
* To use this module, simply include `nimble_rpble` into your build. If nothing
* is explicitly configured, the module will use the default configuration as
* specified in `pkg/nimble/rpble/include/nimble_rpble_params.h`.
*
* Once a node is configured as RPL root (e.g. using the `rpl root ..` shell
* command), it will automatically start to advertise itself. Non-RPL-root nodes
* will automatically scan for potential parent nodes and join the network as
* soon as they find fitting neighbors.
*
*
* ## Implementation status
* In its current state, the implementation only works for environments where a
* single RPL network with a single DODAG are present. The DODAG ID, instance
* ID, and DODAG version are currently pretty much ignored when scanning for
* potential parents.
*
* @{
*
* @file
* @brief Interface for the nimble_rpble module
*
* @author Hauke Petersen <[email protected]>
*/

#ifndef NIMBLE_RPBLE_H
#define NIMBLE_RPBLE_H

#include "nimble_netif.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief rpble configuration parameters
*/
typedef struct {
uint32_t scan_itvl_ms; /**< scan interval when scanning for parents,
* in ms */
uint32_t scan_win_ms; /**< scan window when scanning for parents,
* in ms */
uint32_t adv_itvl_ms; /**< advertising interval used when advertising
* RPL context to child nodes, in ms */
uint32_t conn_scan_itvl_ms; /**< scan interval when connecting to parent,
* in ms */
uint32_t conn_scan_win_ms; /**< scan window when connecting to parent, in
* ms */
uint32_t conn_scan_to_ms; /**< timeout when connecting to parent, in ms */
uint32_t conn_itvl_min_ms; /**< lower bound of connection interval range,
* in ms */
uint32_t conn_itvl_max_ms; /**< upper bound of connection interval range,
in ms */
uint16_t conn_latency; /**< used slave latency for parent connection */
uint32_t conn_super_to_ms; /**< used supervision timeout for parent
* connection, in ms */
uint32_t eval_itvl_min_ms; /**< amount of time a node searches for
* potential parents, lower bound in ms */
uint32_t eval_itvl_max_ms; /**< amount of time a node searches for
* potential parents, upper bound in ms */
} nimble_rpble_cfg_t;

/**
* @brief RPL DODAG information
*/
typedef struct {
uint8_t inst_id; /**< instance ID */
uint8_t dodag_id[16]; /**< DODAG ID */
uint8_t version; /**< DODAG version */
uint8_t role; /**< RPL role of the node */
uint16_t rank; /**< the node's rank in the DODAG */
} nimble_rpble_ctx_t;

/**
* @brief Initialize the nimble_rpble module with the given parameters
*
* @note This function must be called only once, typically during system
* initialization
*
* @param[in] cfg configuration parameters
*
* @return 0 on success
*/
int nimble_rpble_init(const nimble_rpble_cfg_t *cfg);

/**
* @brief Update the used timing parameters
*
* @param[in] cfg configuration parameters
*
* @return 0 on success
*/
int nimble_rpble_param_update(const nimble_rpble_cfg_t *cfg);

/**
* @brief Register a callback that is called on BLE events
*
* The registered callback function is a simple pass-through of nimble_netif
* events. The callback is executed in the context of NimBLE's host thread.
*
* @param[in] cb event callback to register, set to NULL to remove
*/
int nimble_rpble_eventcb(nimble_netif_eventcb_t cb);

/**
* @brief Update the current RPL context
*
* @note This function is meant to be called only by the RPL implementation
*
* @param[in] ctx current DODAG state
* @return 0 on success
* @return -EALREADY if the given context did not change
*/
int nimble_rpble_update(const nimble_rpble_ctx_t *ctx);

#ifdef __cplusplus
}
#endif

#endif /* NIMBLE_RPBLE_H */
/** @} */
99 changes: 99 additions & 0 deletions pkg/nimble/rpble/include/nimble_rpble_params.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2019 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup pkg_nimble_rpble
*
* @{
* @file
* @brief Default configuration for the nimble_netif_rpble module
*
* @author Hauke Petersen <[email protected]>
*/

#ifndef NIMBLE_RPBLE_PARAMS_H
#define NIMBLE_RPBLE_PARAMS_H

#include "nimble_rpble.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* @name Default parameters used for the nimble_netif_rpble module
* @{
*/
#ifndef NIMBLE_RPBLE_SCAN_ITVL_MS
#define NIMBLE_RPBLE_SCAN_ITVL_MS 1200U
#endif
#ifndef NIMBLE_RPBLE_SCAN_WIN_MS
#define NIMBLE_RPBLE_SCAN_WIN_MS 120U
#endif

#ifndef NIMBLE_RPBLE_ADV_ITVL_MS
#define NIMBLE_RPBLE_ADV_ITVL_MS 100U
#endif

#ifndef NIMBLE_RPBLE_CONN_SCAN_ITVL_MS
#define NIMBLE_RPBLE_CONN_SCAN_ITVL_MS 120U
#endif
#ifndef NIMBLE_RPBLE_CONN_SCAN_WIN_MS
#define NIMBLE_RPBLE_CONN_SCAN_WIN_MS 120U
#endif
#ifndef NIMBLE_RPBLE_CONN_SCAN_TO_MS
#define NIMBLE_RPBLE_CONN_SCAN_TO_MS 360U
#endif
#ifndef NIMBLE_RPBLE_CONN_ITVL_MIN_MS
#define NIMBLE_RPBLE_CONN_ITVL_MIN_MS 90U
#endif
#ifndef NIMBLE_RPBLE_CONN_ITVL_MAX_MS
#define NIMBLE_RPBLE_CONN_ITVL_MAX_MS 110U
#endif
#ifndef NIMBLE_RPBLE_CONN_LATENCY
#define NIMBLE_RPBLE_CONN_LATENCY 0
#endif
#ifndef NIMBLE_RPBLE_CONN_SUPER_TO_MS
#define NIMBLE_RPBLE_CONN_SUPER_TO_MS 1650U
#endif

#ifndef NIMBLE_RPBLE_EVAL_ITVL_MIN_MS
#define NIMBLE_RPBLE_EVAL_ITVL_MIN_MS 12000U
#endif
#ifndef NIMBLE_RPBLE_EVAL_ITVL_MAX_MS
#define NIMBLE_RPBLE_EVAL_ITVL_MAX_MS 13000U
#endif

#ifndef NIMBLE_RPBLE_PARAMS
#define NIMBLE_RPBLE_PARAMS \
{ .scan_itvl_ms = NIMBLE_RPBLE_SCAN_ITVL_MS, \
.scan_win_ms = NIMBLE_RPBLE_SCAN_WIN_MS, \
.adv_itvl_ms = NIMBLE_RPBLE_ADV_ITVL_MS, \
.conn_scan_itvl_ms = NIMBLE_RPBLE_CONN_SCAN_ITVL_MS, \
.conn_scan_win_ms = NIMBLE_RPBLE_CONN_SCAN_WIN_MS, \
.conn_scan_to_ms = NIMBLE_RPBLE_CONN_SCAN_TO_MS, \
.conn_itvl_min_ms = NIMBLE_RPBLE_CONN_ITVL_MIN_MS, \
.conn_itvl_max_ms = NIMBLE_RPBLE_CONN_ITVL_MAX_MS, \
.conn_latency = NIMBLE_RPBLE_CONN_LATENCY, \
.conn_super_to_ms = NIMBLE_RPBLE_CONN_SUPER_TO_MS, \
.eval_itvl_min_ms = NIMBLE_RPBLE_EVAL_ITVL_MIN_MS, \
.eval_itvl_max_ms = NIMBLE_RPBLE_EVAL_ITVL_MAX_MS }
#endif
/**@}*/

/**
* @brief nimble_netif_rpble configuration
*/
static const nimble_rpble_cfg_t nimble_rpble_params = NIMBLE_RPBLE_PARAMS;

#ifdef __cplusplus
}
#endif

#endif /* NIMBLE_RPBLE_PARAMS_H */
/** @} */
Loading

0 comments on commit be61154

Please sign in to comment.