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 */
908945static 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