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"
5455
5556static char addr_str [IPV6_ADDR_MAX_STR_LEN ];
5657
57- #define GNRC_RPL_GROUNDED_SHIFT (7)
58- #define GNRC_RPL_MOP_SHIFT (3)
59- #define GNRC_RPL_OPT_TRANSIT_E_FLAG_SHIFT (7)
60- #define GNRC_RPL_OPT_TRANSIT_E_FLAG (1 << GNRC_RPL_OPT_TRANSIT_E_FLAG_SHIFT)
61- #define GNRC_RPL_SHIFTED_MOP_MASK (0x7)
62- #define GNRC_RPL_PRF_MASK (0x7)
63- #define GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT (1 << 6)
64-
6558/**
6659 * @brief Checks validity of DIO control messages
6760 *
@@ -628,7 +621,7 @@ static bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt
628621
629622 /* check the DODAG ID */
630623 if (sol -> VID_flags & GNRC_RPL_DIS_SOLICITED_INFO_FLAG_D ) {
631- if (memcmp (& sol -> dodag_id , & inst -> dodag .dodag_id , sizeof ( ipv6_addr_t )) != 0 ) {
624+ if (! ipv6_addr_equal (& sol -> dodag_id , & inst -> dodag .dodag_id ) ) {
632625 DEBUG ("RPL: RPL SOLICITED INFO option, ignore DIS cause: DODAGID mismatch\n" );
633626 return false;
634627 }
@@ -905,6 +898,42 @@ void _recv_DIO_for_new_dodag(gnrc_rpl_instance_t *inst, gnrc_rpl_dio_t *dio, ker
905898
906899}
907900
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+
908937/**
909938 * @brief Handles a received DIO message for an existing DODAG.
910939 *
@@ -914,17 +943,11 @@ void _recv_DIO_for_new_dodag(gnrc_rpl_instance_t *inst, gnrc_rpl_dio_t *dio, ker
914943 * @param[in] len The length of the DIO packet.
915944 */
916945static void _recv_DIO_for_existing_dodag (gnrc_rpl_instance_t * inst , gnrc_rpl_dio_t * dio ,
917- ipv6_addr_t * src , uint16_t len )
946+ ipv6_addr_t * src ,
947+ uint16_t len )
918948{
919949 gnrc_rpl_dodag_t * dodag = & inst -> dodag ;
920950
921- /* ignore dodags with other dodag_id's for now */
922- /* TODO: choose DODAG with better rank */
923- if (memcmp (& dodag -> dodag_id , & dio -> dodag_id , sizeof (ipv6_addr_t )) != 0 ) {
924- DEBUG ("RPL: DIO received from another DODAG, but same instance - ignore\n" );
925- return ;
926- }
927-
928951 if (inst -> mop != ((dio -> g_mop_prf >> GNRC_RPL_MOP_SHIFT ) & GNRC_RPL_SHIFTED_MOP_MASK )) {
929952 DEBUG ("RPL: invalid MOP for this instance.\n" );
930953 return ;
@@ -937,21 +960,6 @@ static void _recv_DIO_for_existing_dodag(gnrc_rpl_instance_t *inst, gnrc_rpl_dio
937960 }
938961#endif
939962
940- if (GNRC_RPL_COUNTER_GREATER_THAN (dio -> version_number , dodag -> version )) {
941- if (dodag -> node_status == GNRC_RPL_ROOT_NODE ) {
942- dodag -> version = GNRC_RPL_COUNTER_INCREMENT (dio -> version_number );
943- trickle_reset_timer (& dodag -> trickle );
944- }
945- else {
946- dodag -> version = dio -> version_number ;
947- gnrc_rpl_local_repair (dodag );
948- }
949- }
950- else if (GNRC_RPL_COUNTER_GREATER_THAN (dodag -> version , dio -> version_number )) {
951- trickle_reset_timer (& dodag -> trickle );
952- return ;
953- }
954-
955963 if (dodag -> node_status == GNRC_RPL_ROOT_NODE ) {
956964 if (byteorder_ntohs (dio -> rank ) != GNRC_RPL_INFINITE_RANK ) {
957965 trickle_increment_counter (& dodag -> trickle );
@@ -996,6 +1004,11 @@ void gnrc_rpl_recv_DIO(gnrc_rpl_dio_t *dio, kernel_pid_t iface, ipv6_addr_t *src
9961004 else if (inst == NULL ) {
9971005 DEBUG ("RPL: Could not allocate a new instance.\n" );
9981006 }
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+ }
9991012 else {
10001013 _recv_DIO_for_existing_dodag (inst , dio , src , len );
10011014 }
@@ -1256,7 +1269,7 @@ void gnrc_rpl_recv_DAO(gnrc_rpl_dao_t *dao, kernel_pid_t iface, ipv6_addr_t *src
12561269
12571270 /* check if the D flag is set before accessing the DODAG id */
12581271 if ((dao -> k_d_flags & GNRC_RPL_DAO_D_BIT )) {
1259- if (memcmp (& dodag -> dodag_id , (ipv6_addr_t * )(dao + 1 ), sizeof ( ipv6_addr_t )) != 0 ) {
1272+ if (! ipv6_addr_equal (& dodag -> dodag_id , (ipv6_addr_t * )(dao + 1 )) ) {
12601273 DEBUG ("RPL: DAO with unknown DODAG id (%s)\n" , _ip_addr_str ((ipv6_addr_t * )(dao + 1 )));
12611274 return ;
12621275 }
@@ -1319,7 +1332,7 @@ void gnrc_rpl_recv_DAO_ACK(gnrc_rpl_dao_ack_t *dao_ack, kernel_pid_t iface, ipv6
13191332
13201333 /* check if the D flag is set before accessing the DODAG id */
13211334 if ((dao_ack -> d_reserved & GNRC_RPL_DAO_ACK_D_BIT )) {
1322- if (memcmp (& dodag -> dodag_id , (ipv6_addr_t * )(dao_ack + 1 ), sizeof ( ipv6_addr_t )) != 0 ) {
1335+ if (! ipv6_addr_equal (& dodag -> dodag_id , (ipv6_addr_t * )(dao_ack + 1 )) ) {
13231336 DEBUG ("RPL: DAO-ACK with unknown DODAG id (%s)\n" ,
13241337 _ip_addr_str ((ipv6_addr_t * )(dao_ack + 1 )));
13251338 return ;
0 commit comments