Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/nimble/contrib/nimble_riot.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "thread.h"
#include "nimble_riot.h"

#include "net/ipv6/addr.h"
Copy link
Contributor Author

@elenaf9 elenaf9 Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import needed here because the {nimble/}host/* imports below have some definitions that conflict with the byteorder.h that net/ipv6/addr.h imports.

#include "nimble/nimble_port.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
Expand Down
1 change: 1 addition & 0 deletions pkg/nimble/rpble/include/nimble_rpble.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ typedef struct {
uint8_t version; /**< DODAG version */
uint8_t role; /**< RPL role of the node */
uint16_t rank; /**< the node's rank in the DODAG */
ipv6_addr_t parent_addr; /**< address of the node's preferred parent */
Copy link
Contributor Author

@elenaf9 elenaf9 Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to know the ipv6 address of the parent because RPL doesn't know anything about L2 addresses..

Storing it in the local rpl context is (for now) the easiest solution, but alternatively we could also build it directly from the l2 address or use the neighbor cache (which would require #21580).

} nimble_rpble_ctx_t;

/**
Expand Down
23 changes: 15 additions & 8 deletions pkg/nimble/rpble/nimble_rpble.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ static void _on_scan_evt(uint8_t type, const ble_addr_t *addr,
static void _parent_find(void)
{
_psel.score = SCORE_NONE;
_current_parent = PARENT_NONE;
nimble_scanner_start();
ble_npl_callout_reset(&_evt_eval, _eval_itvl);
}
Expand Down Expand Up @@ -213,6 +214,18 @@ static void _parent_connect(struct ble_npl_event *ev)
_current_parent = res;
}

static void _parent_lost(void)
{
nimble_netif_accept_stop();

if (_local_rpl_ctx.rank != 0) {
gnrc_rpl_addr_unreachable(&_local_rpl_ctx.parent_addr);
}

/* back to 0, now we need to find a new parent... */
_parent_find();
}

static void _on_netif_evt(int handle, nimble_netif_event_t event,
const uint8_t *addr)
{
Expand All @@ -232,20 +245,14 @@ static void _on_netif_evt(int handle, nimble_netif_event_t event,
break;
case NIMBLE_NETIF_CLOSED_MASTER:
/* parent lost */
nimble_netif_accept_stop();
_current_parent = PARENT_NONE;
/* back to 0, now we need to find a new parent... */
_parent_find();
break;
_parent_lost();
case NIMBLE_NETIF_CLOSED_SLAVE:
/* child lost */
_children_accept();
break;
case NIMBLE_NETIF_ABORT_MASTER:
/* parent selection aborted */
nimble_netif_accept_stop();
_current_parent = PARENT_NONE;
_parent_find();
_parent_lost();
break;
case NIMBLE_NETIF_ABORT_SLAVE:
/* child selection aborted */
Expand Down
10 changes: 10 additions & 0 deletions sys/include/net/gnrc/rpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@
#define GNRC_RPL_COUNTER_MAX (255)
#define GNRC_RPL_COUNTER_LOWER_REGION (127)
#define GNRC_RPL_COUNTER_SEQ_WINDOW (16)
#define GNRC_RPL_COUNTER_INIT (GNRC_RPL_COUNTER_MAX - GNRC_RPL_COUNTER_SEQ_WINDOW + 1)

Check warning on line 300 in sys/include/net/gnrc/rpl.h

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters

static inline uint8_t GNRC_RPL_COUNTER_INCREMENT(uint8_t counter)
{
Expand Down Expand Up @@ -499,7 +499,7 @@
* RFC 6550, section 3.5.1, Rank Comparison (DAGRank())
* </a>
*/
#define DAGRANK(rank,mhri) (rank/mhri)

Check warning on line 502 in sys/include/net/gnrc/rpl.h

View workflow job for this annotation

GitHub Actions / static-tests

comma should be followed by whitespace

/**
* @name Global / Local instance id masks
Expand Down Expand Up @@ -706,6 +706,16 @@
gnrc_rpl_instance_t *gnrc_rpl_root_instance_init(uint8_t instance_id, const ipv6_addr_t *dodag_id,
uint8_t mop);

/**
* @brief Mark an address as unreachable.
*
* @note Connection-oriented link-layers can use this to hint RPL
* that a parent with this address is unreachable.
*
* @param[in] addr Address that became unreachable.
*/
void gnrc_rpl_addr_unreachable(ipv6_addr_t *addr);

/**
* @brief Send a control message
*
Expand Down
12 changes: 12 additions & 0 deletions sys/include/net/gnrc/rpl/dodag.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,18 @@ void gnrc_rpl_dodag_remove_all_parents(gnrc_rpl_dodag_t *dodag);
bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr,
gnrc_rpl_parent_t **parent);

/**
* @brief Iterate over all parents in all DODAGs with IPv6 address @p addr.
*
* @param[in] idx Index to start searching from.
* @param[in] addr IPV6 address of the parent.
* @param[out] parent Pointer to the parent if one was found. Otherwise NULL.
*
* @return Index > 0 to continue next search from, if parent was found.
* @return -ENONENT if not found.
*/
int gnrc_rpl_parent_iter_by_addr(ipv6_addr_t *addr, gnrc_rpl_parent_t **parent, int idx);

Comment on lines +132 to +143
Copy link
Contributor Author

@elenaf9 elenaf9 Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is a bit weird, but it is needed because, theoretically, if we have more than one RPL instance, the same node can be present as parent in multiple dodags, and thus appear multiple times in the gnrc_rpl_parents list.
We want to mark the parent as unreachable in all dodags.

/**
* @brief Remove the @p parent from its DODAG.
*
Expand Down
7 changes: 7 additions & 0 deletions sys/include/net/gnrc/rpl/rpble.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,18 @@ extern "C" {
static inline void gnrc_rpl_rpble_update(const gnrc_rpl_dodag_t *dodag)
{
nimble_rpble_ctx_t ctx;

ctx.inst_id = dodag->instance->id;
memcpy(ctx.dodag_id, &dodag->dodag_id, 16);
ctx.version = dodag->version;
ctx.rank = dodag->my_rank;
ctx.role = dodag->node_status;
if (dodag->parents) {
ctx.parent_addr = dodag->parents->addr;
}
else {
memset(&ctx.parent_addr, 0, sizeof(ipv6_addr_t));
}
nimble_rpble_update(&ctx);
}
#else
Expand Down
24 changes: 24 additions & 0 deletions sys/net/gnrc/routing/rpl/gnrc_rpl.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ gnrc_rpl_instance_t *gnrc_rpl_root_init(uint8_t instance_id, const ipv6_addr_t *
return inst;
}

void gnrc_rpl_addr_unreachable(ipv6_addr_t *addr)
{
msg_t msg;
msg.type = GNRC_RPL_MSG_TYPE_ADDR_UNREACHABLE;
msg.content.ptr = addr;
msg_send(&msg, gnrc_rpl_pid);
Comment on lines +182 to +184
Copy link
Contributor Author

@elenaf9 elenaf9 Jul 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this cause an issue if it ends-up blocking the caller (in my case the nimble thread)? We need to use IPC because the rpl data structures aren't thread safe.

}

static void _receive(gnrc_pktsnip_t *icmpv6)
{
gnrc_pktsnip_t *ipv6, *netif;
Expand Down Expand Up @@ -273,6 +281,16 @@ static void _parent_timeout(gnrc_rpl_parent_t *parent)
evtimer_add_msg(&gnrc_rpl_evtimer, &parent->timeout_event, gnrc_rpl_pid);
}

static void _addr_unreachable(ipv6_addr_t *addr)
{
gnrc_rpl_parent_t *parent;
int idx = 0;

while ((idx = gnrc_rpl_parent_iter_by_addr(addr, &parent, idx)) >= 0) {
_parent_timeout(parent);
}
}

static void *_event_loop(void *args)
{
msg_t msg, reply;
Expand All @@ -293,6 +311,7 @@ static void *_event_loop(void *args)
trickle_t *trickle;
gnrc_rpl_parent_t *parent;
gnrc_rpl_instance_t *instance;
ipv6_addr_t *addr;

/* start event loop */
while (1) {
Expand All @@ -311,6 +330,11 @@ static void *_event_loop(void *args)
parent = msg.content.ptr;
_parent_timeout(parent);
break;
case GNRC_RPL_MSG_TYPE_ADDR_UNREACHABLE:
DEBUG("RPL: GNRC_RPL_MSG_TYPE_ADDR_UNREACHABLE received\n");
addr = msg.content.ptr;
_addr_unreachable(addr);
break;
case GNRC_RPL_MSG_TYPE_DODAG_DAO_TX:
DEBUG("RPL: GNRC_RPL_MSG_TYPE_DODAG_DAO_TX received\n");
instance = msg.content.ptr;
Expand Down
12 changes: 12 additions & 0 deletions sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@

gnrc_rpl_send_DIO(inst, (ipv6_addr_t *) &ipv6_addr_all_rpl_nodes);
DEBUG("trickle callback: Instance (%d) | DODAG: (%s)\n", inst->id,
ipv6_addr_to_str(addr_str,&dodag->dodag_id, sizeof(addr_str)));

Check warning on line 68 in sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c

View workflow job for this annotation

GitHub Actions / static-tests

comma should be followed by whitespace
}

/* The lifetime of the default route should exceed the parent timeout interval
Expand Down Expand Up @@ -113,7 +113,7 @@

bool gnrc_rpl_instance_remove_by_id(uint8_t instance_id)
{
for(uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {

Check warning on line 116 in sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c

View workflow job for this annotation

GitHub Actions / static-tests

keyword 'for' not followed by a single space
if (gnrc_rpl_instances[i].id == instance_id) {
return gnrc_rpl_instance_remove(&gnrc_rpl_instances[i]);
}
Expand Down Expand Up @@ -196,6 +196,18 @@
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
}

int gnrc_rpl_parent_iter_by_addr(ipv6_addr_t *addr, gnrc_rpl_parent_t **parent, int idx)
{
*parent = NULL;
for (uint8_t i = idx; i < GNRC_RPL_PARENTS_NUMOF; ++i) {
if ((gnrc_rpl_parents[i].state != 0) && ipv6_addr_equal(&gnrc_rpl_parents[i].addr, addr)) {
*parent = &gnrc_rpl_parents[i];
return i + 1;
}
}
return -ENOENT;
}

bool gnrc_rpl_parent_add_by_addr(gnrc_rpl_dodag_t *dodag, ipv6_addr_t *addr,
gnrc_rpl_parent_t **parent)
{
Expand Down Expand Up @@ -223,7 +235,7 @@
(*parent)->state = GNRC_RPL_PARENT_ACTIVE;
(*parent)->addr = *addr;
(*parent)->rank = GNRC_RPL_INFINITE_RANK;
evtimer_del((evtimer_t *)(&gnrc_rpl_evtimer), (evtimer_event_t *)(&(*parent)->timeout_event));

Check warning on line 238 in sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
((evtimer_event_t *)(&(*parent)->timeout_event))->next = NULL;
(*parent)->timeout_event.msg.type = GNRC_RPL_MSG_TYPE_PARENT_TIMEOUT;
(*parent)->timeout_event.msg.content.ptr = (*parent);
Expand Down Expand Up @@ -259,7 +271,7 @@

void gnrc_rpl_cleanup_start(gnrc_rpl_dodag_t *dodag)
{
evtimer_del((evtimer_t *)(&gnrc_rpl_evtimer), (evtimer_event_t *)&dodag->instance->cleanup_event);

Check warning on line 274 in sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
((evtimer_event_t *)&(dodag->instance->cleanup_event))->offset = CONFIG_GNRC_RPL_CLEANUP_TIME;
dodag->instance->cleanup_event.msg.type = GNRC_RPL_MSG_TYPE_INSTANCE_CLEANUP;
evtimer_add_msg(&gnrc_rpl_evtimer, &dodag->instance->cleanup_event, gnrc_rpl_pid);
Expand Down Expand Up @@ -289,7 +301,7 @@
if ((parent != NULL) && (parent->state != GNRC_RPL_PARENT_UNUSED)) {
parent->state = GNRC_RPL_PARENT_ACTIVE;
evtimer_del((evtimer_t *)(&gnrc_rpl_evtimer), (evtimer_event_t *)&parent->timeout_event);
((evtimer_event_t *)&(parent->timeout_event))->offset = (dodag->default_lifetime - 1) * dodag->lifetime_unit * MS_PER_SEC;

Check warning on line 304 in sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c

View workflow job for this annotation

GitHub Actions / static-tests

line is longer than 100 characters
parent->timeout_event.msg.type = GNRC_RPL_MSG_TYPE_PARENT_TIMEOUT;
evtimer_add_msg(&gnrc_rpl_evtimer, &parent->timeout_event, gnrc_rpl_pid);
#ifdef MODULE_GNRC_RPL_P2P
Expand Down
4 changes: 4 additions & 0 deletions sys/net/gnrc/routing/rpl/gnrc_rpl_internal/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ extern evtimer_msg_t gnrc_rpl_evtimer;
* @brief Message type for DAO transmissions.
*/
#define GNRC_RPL_MSG_TYPE_DODAG_DAO_TX (0x0906)
/**
* @brief Message type for signaling an unreachable address.
*/
#define GNRC_RPL_MSG_TYPE_ADDR_UNREACHABLE (0x0907)
/** @} */

/**
Expand Down
Loading