Skip to content

Commit a96e5e7

Browse files
committed
gnrc/rpl: float DODAG during local repair
If the parent set of a router is empty and a local repair initiated, don't immediately poison all routes. Instead configure node as root of a new floating DODAG to maintain connectivity in the sub-tree. Once a different, grounded DODAG is found the node will join the new DODAG. If no other DODAG is found the floating DODAG will timeout after `CONFIG_GNRC_RPL_DODAG_FLOAT_TIMEOUT` and cleaned up..
1 parent ff012b7 commit a96e5e7

File tree

6 files changed

+83
-5
lines changed

6 files changed

+83
-5
lines changed

sys/include/net/gnrc/rpl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@
151151
#include "net/gnrc/rpl/dodag.h"
152152
#include "net/gnrc/rpl/of_manager.h"
153153
#include "net/fib.h"
154+
#include "time_units.h"
154155
#include "trickle.h"
155156

156157
#ifdef MODULE_NETSTATS_RPL
@@ -627,6 +628,13 @@ extern netstats_rpl_t gnrc_rpl_netstats;
627628
#define CONFIG_GNRC_RPL_PARENT_TIMEOUT_DIS_RETRIES (3)
628629
#endif
629630

631+
/**
632+
* @brief Timeout for floating DODAGs in milliseconds.
633+
*/
634+
#ifndef CONFIG_GNRC_RPL_DODAG_FLOAT_TIMEOUT
635+
# define CONFIG_GNRC_RPL_DODAG_FLOAT_TIMEOUT (15 * MS_PER_SEC * SEC_PER_MIN)
636+
#endif
637+
630638
/**
631639
* @brief Default network interface for GNRC RPL
632640
*/

sys/include/net/gnrc/rpl/dodag.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,15 @@ void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent);
166166
*/
167167
void gnrc_rpl_cleanup_start(gnrc_rpl_dodag_t *dodag);
168168

169+
/**
170+
* @brief Poison all routes of @p dodag by setting an infinite rank, and schedule
171+
* a cleanup for the @p dodag.
172+
*
173+
* @param[in] dodag Pointer to the DODAG
174+
*
175+
*/
176+
void gnrc_rpl_poison_routes(gnrc_rpl_dodag_t *dodag);
177+
169178
/**
170179
* @brief Start a local repair.
171180
*

sys/include/net/gnrc/rpl/structs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,10 @@ struct gnrc_rpl_dodag {
330330
uint8_t dio_opts; /**< options in the next DIO
331331
(see @ref GNRC_RPL_REQ_DIO_OPTS "DIO Options") */
332332
evtimer_msg_event_t dao_event; /**< DAO TX events (see @ref GNRC_RPL_MSG_TYPE_DODAG_DAO_TX) */
333+
/**
334+
* floating dodag timeout events (see @ref GNRC_RPL_MSG_TYPE_DODAG_FLOAT_TIMEOUT)
335+
*/
336+
evtimer_msg_event_t float_timeout_event;
333337
trickle_t trickle; /**< trickle representation */
334338
};
335339

sys/net/gnrc/routing/rpl/gnrc_rpl.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,15 @@ static void _parent_timeout(gnrc_rpl_parent_t *parent)
250250
evtimer_add_msg(&gnrc_rpl_evtimer, &parent->timeout_event, gnrc_rpl_pid);
251251
}
252252

253+
/* Handle timeout for floating DODAG by poisoning all routes. */
254+
static void _dodag_float_timeout(gnrc_rpl_dodag_t *dodag)
255+
{
256+
if (dodag->grounded != GNRC_RPL_GROUNDED) {
257+
gnrc_rpl_poison_routes(dodag);
258+
}
259+
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&dodag->float_timeout_event);
260+
}
261+
253262
static void *_event_loop(void *args)
254263
{
255264
msg_t msg, reply;
@@ -300,6 +309,11 @@ static void *_event_loop(void *args)
300309
gnrc_rpl_instance_remove(instance);
301310
}
302311
break;
312+
case GNRC_RPL_MSG_TYPE_DODAG_FLOAT_TIMEOUT:
313+
DEBUG("RPL: GNRC_RPL_MSG_TYPE_DODAG_FLOAT_TIMEOUT received\n");
314+
instance = msg.content.ptr;
315+
_dodag_float_timeout(&instance->dodag);
316+
break;
303317
case GNRC_RPL_MSG_TYPE_TRICKLE_MSG:
304318
DEBUG("RPL: GNRC_RPL_MSG_TYPE_TRICKLE_MSG received\n");
305319
trickle = msg.content.ptr;

sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ static uint16_t _dflt_route_lifetime_sec(gnrc_rpl_dodag_t *dodag)
7777
(GNRC_RPL_PARENT_PROBE_INTERVAL / MS_PER_SEC));
7878
}
7979

80+
void gnrc_rpl_poison_routes(gnrc_rpl_dodag_t *dodag)
81+
{
82+
if (dodag->my_rank != GNRC_RPL_INFINITE_RANK) {
83+
DEBUG("RPL: Poison all children routes in DODAG.\n");
84+
85+
/* Poison routes by advertising infinity rank */
86+
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
87+
trickle_reset_timer(&dodag->trickle);
88+
gnrc_rpl_cleanup_start(dodag);
89+
}
90+
}
91+
8092
bool gnrc_rpl_instance_add(uint8_t instance_id, gnrc_rpl_instance_t **inst)
8193
{
8294
*inst = NULL;
@@ -130,8 +142,9 @@ void gnrc_rpl_dodag_remove(gnrc_rpl_dodag_t *dodag)
130142
gnrc_rpl_dodag_remove_all_parents(dodag);
131143
trickle_stop(&dodag->trickle);
132144
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&dodag->dao_event);
145+
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&dodag->float_timeout_event);
133146
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&dodag->instance->cleanup_event);
134-
147+
memset(dodag, 0, sizeof(gnrc_rpl_dodag_t));
135148
}
136149

137150
void gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst)
@@ -200,6 +213,8 @@ bool gnrc_rpl_dodag_init(gnrc_rpl_instance_t *instance, const ipv6_addr_t *dodag
200213
dodag->iface = iface;
201214
dodag->dao_event.msg.content.ptr = instance;
202215
dodag->dao_event.msg.type = GNRC_RPL_MSG_TYPE_DODAG_DAO_TX;
216+
dodag->float_timeout_event.msg.content.ptr = instance;
217+
dodag->float_timeout_event.msg.type = GNRC_RPL_MSG_TYPE_DODAG_FLOAT_TIMEOUT;
203218

204219
if ((netif != NULL) && !(netif->flags & GNRC_NETIF_FLAGS_IPV6_FORWARDING)) {
205220
gnrc_rpl_leaf_operation(dodag);
@@ -215,6 +230,32 @@ bool gnrc_rpl_dodag_init(gnrc_rpl_instance_t *instance, const ipv6_addr_t *dodag
215230
return true;
216231
}
217232

233+
bool _float_dodag(gnrc_rpl_dodag_t *dodag)
234+
{
235+
evtimer_event_t *float_event = (evtimer_event_t *)&dodag->float_timeout_event;
236+
237+
DEBUG("RPL: Set node as root for floating DODAG.\n");
238+
239+
evtimer_del(&gnrc_rpl_evtimer, float_event);
240+
241+
/* find address on interface that matches the prefix of the old dodag */
242+
gnrc_netif_t *netif = gnrc_netif_get_by_pid(dodag->iface);
243+
int idx = gnrc_netif_ipv6_addr_match(netif, &dodag->dodag_id);
244+
if (idx < 0) {
245+
DEBUG("RPL: could not find address to use as DODAGID.");
246+
return false;
247+
}
248+
dodag->dodag_id = netif->ipv6.addrs[idx];
249+
gnrc_rpl_dodag_root_init(dodag);
250+
dodag->grounded &= !GNRC_RPL_GROUNDED;
251+
252+
/* floating dodag should timeout eventually if no new grounded dodag is found */
253+
float_event->offset = CONFIG_GNRC_RPL_DODAG_FLOAT_TIMEOUT;
254+
evtimer_add_msg(&gnrc_rpl_evtimer, &dodag->float_timeout_event, gnrc_rpl_pid);
255+
256+
return true;
257+
}
258+
218259
void gnrc_rpl_dodag_remove_all_parents(gnrc_rpl_dodag_t *dodag)
219260
{
220261
gnrc_rpl_parent_t *elt = NULL;
@@ -300,10 +341,8 @@ void gnrc_rpl_local_repair(gnrc_rpl_dodag_t *dodag)
300341

301342
dodag->dtsn++;
302343

303-
if (dodag->my_rank != GNRC_RPL_INFINITE_RANK) {
304-
dodag->my_rank = GNRC_RPL_INFINITE_RANK;
305-
trickle_reset_timer(&dodag->trickle);
306-
gnrc_rpl_cleanup_start(dodag);
344+
if ((CONFIG_GNRC_RPL_DODAG_FLOAT_TIMEOUT <= 0) || !_float_dodag(dodag)) {
345+
gnrc_rpl_poison_routes(dodag);
307346
}
308347

309348
if (dodag->parents) {

sys/net/gnrc/routing/rpl/gnrc_rpl_internal/globals.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ extern evtimer_msg_t gnrc_rpl_evtimer;
4545
* @brief Message type for DAO transmissions.
4646
*/
4747
#define GNRC_RPL_MSG_TYPE_DODAG_DAO_TX (0x0906)
48+
/**
49+
* @brief Message type for floating DODAG timeouts.
50+
*/
51+
#define GNRC_RPL_MSG_TYPE_DODAG_FLOAT_TIMEOUT (0x0907)
4852
/** @} */
4953

5054
/**

0 commit comments

Comments
 (0)