@@ -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+
8092bool 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
137150void 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+
218259void 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 ) {
0 commit comments