Skip to content

Commit 523d70e

Browse files
committed
gnrc/rpl/control_messages: handle DIO of different DODAG
1 parent 0081a6e commit 523d70e

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

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

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "net/gnrc.h"
3636
#include "net/eui64.h"
3737
#include "gnrc_rpl_internal/globals.h"
38+
#include "of0.h"
3839

3940
#ifdef MODULE_NETSTATS_RPL
4041
#include "gnrc_rpl_internal/netstats.h"
@@ -897,6 +898,42 @@ void _recv_DIO_for_new_dodag(gnrc_rpl_instance_t *inst, gnrc_rpl_dio_t *dio, ker
897898

898899
}
899900

901+
/**
902+
* @brief Handles a received DIO message for a DODAG that is different from the
903+
* one we currently participate in.
904+
*
905+
* @param[in] inst The @p RPL instance of the current DODAG.
906+
* @param[in] dio The @p DIO packet for the other DODAG.
907+
* @param[in] src The address of the sender.
908+
* @param[in] len The length of the DIO packet.
909+
*/
910+
static void _recv_DIO_for_different_dodag(gnrc_rpl_instance_t *inst, gnrc_rpl_dio_t *dio,
911+
kernel_pid_t iface,
912+
ipv6_addr_t *src, uint16_t len)
913+
{
914+
/* DIO received from a different DODAG */
915+
DEBUG("RPL: DIO received from another DODAG, but same instance.\n");
916+
917+
gnrc_rpl_dodag_t *dodag = &inst->dodag;
918+
919+
/* clear parent from old dodag if present */
920+
gnrc_rpl_parent_t *parent = dodag->parents;
921+
while (parent) {
922+
if (ipv6_addr_equal(&parent->addr, src)) {
923+
gnrc_rpl_parent_remove(parent);
924+
break;
925+
}
926+
parent = parent->next;
927+
}
928+
929+
/* decide between old and new dodag */
930+
if (gnrc_rpl_get_of0()->which_dodag(dodag, dio) > 0) {
931+
DEBUG("RPL: switch to new DODAG.\n");
932+
gnrc_rpl_dodag_remove(dodag);
933+
_recv_DIO_for_new_dodag(inst, dio, iface, src, len);
934+
}
935+
}
936+
900937
/**
901938
* @brief Handles a received DIO message for an existing DODAG.
902939
*
@@ -906,17 +943,11 @@ void _recv_DIO_for_new_dodag(gnrc_rpl_instance_t *inst, gnrc_rpl_dio_t *dio, ker
906943
* @param[in] len The length of the DIO packet.
907944
*/
908945
static void _recv_DIO_for_existing_dodag(gnrc_rpl_instance_t *inst, gnrc_rpl_dio_t *dio,
909-
ipv6_addr_t *src, uint16_t len)
946+
ipv6_addr_t *src,
947+
uint16_t len)
910948
{
911949
gnrc_rpl_dodag_t *dodag = &inst->dodag;
912950

913-
/* ignore dodags with other dodag_id's for now */
914-
/* TODO: choose DODAG with better rank */
915-
if (!ipv6_addr_equal(&dodag->dodag_id, &dio->dodag_id)) {
916-
DEBUG("RPL: DIO received from another DODAG, but same instance - ignore\n");
917-
return;
918-
}
919-
920951
if (inst->mop != ((dio->g_mop_prf >> GNRC_RPL_MOP_SHIFT) & GNRC_RPL_SHIFTED_MOP_MASK)) {
921952
DEBUG("RPL: invalid MOP for this instance.\n");
922953
return;
@@ -929,21 +960,6 @@ static void _recv_DIO_for_existing_dodag(gnrc_rpl_instance_t *inst, gnrc_rpl_dio
929960
}
930961
#endif
931962

932-
if (GNRC_RPL_COUNTER_GREATER_THAN(dio->version_number, dodag->version)) {
933-
if (dodag->node_status == GNRC_RPL_ROOT_NODE) {
934-
dodag->version = GNRC_RPL_COUNTER_INCREMENT(dio->version_number);
935-
trickle_reset_timer(&dodag->trickle);
936-
}
937-
else {
938-
dodag->version = dio->version_number;
939-
gnrc_rpl_local_repair(dodag);
940-
}
941-
}
942-
else if (GNRC_RPL_COUNTER_GREATER_THAN(dodag->version, dio->version_number)) {
943-
trickle_reset_timer(&dodag->trickle);
944-
return;
945-
}
946-
947963
if (dodag->node_status == GNRC_RPL_ROOT_NODE) {
948964
if (byteorder_ntohs(dio->rank) != GNRC_RPL_INFINITE_RANK) {
949965
trickle_increment_counter(&dodag->trickle);
@@ -988,6 +1004,11 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, kernel_pid_t iface, ipv6_addr_t *src
9881004
else if (inst == NULL) {
9891005
DEBUG("RPL: Could not allocate a new instance.\n");
9901006
}
1007+
else if (!ipv6_addr_equal(&inst->dodag.dodag_id, &dio->dodag_id)
1008+
|| (inst->dodag.version != dio->version_number)) {
1009+
1010+
_recv_DIO_for_different_dodag(inst, dio, iface, src, len);
1011+
}
9911012
else {
9921013
_recv_DIO_for_existing_dodag(inst, dio, src, len);
9931014
}

0 commit comments

Comments
 (0)