Skip to content

Commit 08799d9

Browse files
authored
Merge pull request #21759 from elenaf9/gnrc/rpl/different-dodags
gnrc/rpl: switching between DODAGs
2 parents 5ff98db + 523d70e commit 08799d9

File tree

7 files changed

+195
-60
lines changed

7 files changed

+195
-60
lines changed

sys/include/net/gnrc/rpl.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,18 +439,84 @@ static inline bool GNRC_RPL_COUNTER_GREATER_THAN(uint8_t A, uint8_t B)
439439
* </a>
440440
* @{
441441
*/
442+
/**
443+
* @brief Type ID of the Pad1 option.
444+
*/
442445
#define GNRC_RPL_OPT_PAD1 (0)
446+
/**
447+
* @brief Type ID of the PadN option.
448+
*/
443449
#define GNRC_RPL_OPT_PADN (1)
450+
/**
451+
* @brief Type ID of the DAG Metric Container option.
452+
*/
444453
#define GNRC_RPL_OPT_DAG_METRIC_CONTAINER (2)
454+
/**
455+
* @brief Type ID of the Route Information option.
456+
*/
445457
#define GNRC_RPL_OPT_ROUTE_INFO (3)
458+
/**
459+
* @brief Type ID of the DODAG Configuration option.
460+
*/
446461
#define GNRC_RPL_OPT_DODAG_CONF (4)
462+
/**
463+
* @brief Type ID of the RPL Target option.
464+
*/
447465
#define GNRC_RPL_OPT_TARGET (5)
466+
/**
467+
* @brief Type ID of the Transit Information option.
468+
*/
448469
#define GNRC_RPL_OPT_TRANSIT (6)
470+
/**
471+
* @brief Shift of the External 'E' flag in the Transit
472+
* Information flags.
473+
*/
474+
#define GNRC_RPL_OPT_TRANSIT_E_FLAG_SHIFT (7)
475+
/**
476+
* @brief Type ID of the Solocited option.
477+
*/
449478
#define GNRC_RPL_OPT_SOLICITED_INFO (7)
479+
/**
480+
* @brief Type ID of the Prefix Information option.
481+
*/
450482
#define GNRC_RPL_OPT_PREFIX_INFO (8)
483+
/**
484+
* @brief Shift of the autnomous address-configuration
485+
* 'A' flag in the Prefix Information option.
486+
*/
487+
#define GNRC_RPL_PREFIX_AUTO_ADDRESS_BIT (1 << 6)
488+
/**
489+
* @brief Type ID of the RPL Target Descriptor option.
490+
*/
451491
#define GNRC_RPL_OPT_TARGET_DESC (9)
452492
/** @} */
453493

494+
/**
495+
* @name RPL DIO Base Object fields
496+
* @see <a href="https://tools.ietf.org/html/rfc6550#section-6.3">
497+
* DODAG Information Object (DIO)
498+
* </a>
499+
* @{
500+
*/
501+
/**
502+
* @brief Shift of the Grounded 'G' flag in the DIO.
503+
*/
504+
#define GNRC_RPL_GROUNDED_SHIFT (7)
505+
/**
506+
* @brief Shift of the Mode of Operation (MOP) field in the DIO.
507+
*/
508+
#define GNRC_RPL_MOP_SHIFT (3)
509+
/**
510+
* @brief Mask for the 3 MOP bits.
511+
*/
512+
#define GNRC_RPL_SHIFTED_MOP_MASK (0x7)
513+
/**
514+
* @brief Mask for the 3 PRF bits.
515+
*/
516+
#define GNRC_RPL_PRF_MASK (0x7)
517+
/** @} */
518+
519+
454520
/**
455521
* @brief Rank of the root node
456522
*/

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,19 @@ bool gnrc_rpl_instance_add(uint8_t instance_id, gnrc_rpl_instance_t **inst);
7676
*/
7777
bool gnrc_rpl_instance_remove_by_id(uint8_t instance_id);
7878

79+
/**
80+
* @brief Remove a RPL DODAG with the pointer @p dodag from its instance.
81+
*
82+
* @param[in] dodag Pointer to the RPL DODAG to remove.
83+
*/
84+
void gnrc_rpl_dodag_remove(gnrc_rpl_dodag_t *dodag);
85+
7986
/**
8087
* @brief Remove a RPL instance with the pointer @p inst.
8188
*
8289
* @param[in] inst Pointer to the RPL instance to remove.
83-
*
84-
* @return true, on success.
85-
* @return false, otherwise.
8690
*/
87-
bool gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst);
91+
void gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst);
8892

8993
/**
9094
* @brief Get the RPL instance with the id @p instance_id.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ typedef struct {
286286
* @return Negative, if the first parent is preferred.
287287
*/
288288
int (*parent_cmp)(gnrc_rpl_parent_t *parent1, gnrc_rpl_parent_t *parent2);
289-
gnrc_rpl_dodag_t *(*which_dodag)(gnrc_rpl_dodag_t *, gnrc_rpl_dodag_t *); /**< compare for dodags */
289+
int (*which_dodag)(gnrc_rpl_dodag_t *, gnrc_rpl_dio_t *); /**< compare for dodags */
290290

291291
/**
292292
* @brief Reset the state of the objective function.

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

Lines changed: 47 additions & 34 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"
@@ -54,14 +55,6 @@
5455

5556
static 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
*/
916945
static 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;

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,24 +115,29 @@ bool gnrc_rpl_instance_remove_by_id(uint8_t instance_id)
115115
{
116116
for(uint8_t i = 0; i < GNRC_RPL_INSTANCES_NUMOF; ++i) {
117117
if (gnrc_rpl_instances[i].id == instance_id) {
118-
return gnrc_rpl_instance_remove(&gnrc_rpl_instances[i]);
118+
gnrc_rpl_instance_remove(&gnrc_rpl_instances[i]);
119+
return true;
119120
}
120121
}
121122
return false;
122123
}
123124

124-
bool gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst)
125+
void gnrc_rpl_dodag_remove(gnrc_rpl_dodag_t *dodag)
125126
{
126-
gnrc_rpl_dodag_t *dodag = &inst->dodag;
127127
#ifdef MODULE_GNRC_RPL_P2P
128128
gnrc_rpl_p2p_ext_remove(dodag);
129129
#endif
130130
gnrc_rpl_dodag_remove_all_parents(dodag);
131131
trickle_stop(&dodag->trickle);
132132
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&dodag->dao_event);
133-
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&inst->cleanup_event);
133+
evtimer_del(&gnrc_rpl_evtimer, (evtimer_event_t *)&dodag->instance->cleanup_event);
134+
135+
}
136+
137+
void gnrc_rpl_instance_remove(gnrc_rpl_instance_t *inst)
138+
{
139+
gnrc_rpl_dodag_remove(&inst->dodag);
134140
memset(inst, 0, sizeof(gnrc_rpl_instance_t));
135-
return true;
136141
}
137142

138143
gnrc_rpl_instance_t *gnrc_rpl_instance_get(uint8_t instance_id)

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

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@
2525

2626
static uint16_t calc_rank(gnrc_rpl_dodag_t *, uint16_t);
2727
static int parent_cmp(gnrc_rpl_parent_t *, gnrc_rpl_parent_t *);
28-
static gnrc_rpl_dodag_t *which_dodag(gnrc_rpl_dodag_t *, gnrc_rpl_dodag_t *);
28+
static int which_dodag(gnrc_rpl_dodag_t *, gnrc_rpl_dio_t *);
2929
static void reset(gnrc_rpl_dodag_t *);
3030

3131
static gnrc_rpl_of_t gnrc_rpl_of0 = {
32-
.ocp = 0x0,
33-
.calc_rank = calc_rank,
34-
.parent_cmp = parent_cmp,
35-
.which_dodag = which_dodag,
36-
.reset = reset,
32+
.ocp = 0x0,
33+
.calc_rank = calc_rank,
34+
.parent_cmp = parent_cmp,
35+
.which_dodag = which_dodag,
36+
.reset = reset,
3737
.parent_state_callback = NULL,
38-
.init = NULL,
39-
.process_dio = NULL
38+
.init = NULL,
39+
.process_dio = NULL
4040
};
4141

4242
gnrc_rpl_of_t *gnrc_rpl_get_of0(void)
@@ -87,9 +87,59 @@ int parent_cmp(gnrc_rpl_parent_t *parent1, gnrc_rpl_parent_t *parent2)
8787
return 0;
8888
}
8989

90-
/* Not used yet */
91-
gnrc_rpl_dodag_t *which_dodag(gnrc_rpl_dodag_t *d1, gnrc_rpl_dodag_t *d2)
90+
int which_dodag(gnrc_rpl_dodag_t *d1, gnrc_rpl_dio_t *dio)
9291
{
93-
(void) d2;
94-
return d1;
92+
/* RFC 6552, Section 4.2 */
93+
94+
/* parent set must not be empty */
95+
if ((d1->node_status != GNRC_RPL_ROOT_NODE) && !d1->parents) {
96+
return 1;
97+
}
98+
99+
/* prefer grounded dodag */
100+
int dio_grounded = dio->g_mop_prf >> GNRC_RPL_GROUNDED_SHIFT;
101+
if (d1->grounded > dio_grounded) {
102+
return -1;
103+
}
104+
else if (dio_grounded > d1->grounded) {
105+
return 1;
106+
}
107+
108+
int dio_prf = dio->g_mop_prf & GNRC_RPL_PRF_MASK;
109+
110+
/* prefer dodag with more preferable root */
111+
if (d1->prf > dio_prf) {
112+
return -1;
113+
}
114+
else if (dio_prf > d1->prf) {
115+
return 1;
116+
}
117+
118+
/* prefer DODAG with more recent version */
119+
if (ipv6_addr_equal(&d1->dodag_id, &dio->dodag_id)) {
120+
if (GNRC_RPL_COUNTER_GREATER_THAN(d1->version, dio->version_number)) {
121+
return -1;
122+
}
123+
else if (GNRC_RPL_COUNTER_GREATER_THAN(dio->version_number, d1->version)) {
124+
return 1;
125+
}
126+
}
127+
128+
/* prefer dodag with lesser resulting rank */
129+
/* TODO: calc rank properly */
130+
int d1_rank = d1->parents->rank;
131+
int d2_rank = byteorder_ntohs(dio->rank);
132+
if (d1_rank < d2_rank) {
133+
return -1;
134+
}
135+
else if (d2_rank < d1_rank) {
136+
return 1;
137+
}
138+
139+
/* prefer DODAG for which there is an alternate parent */
140+
if (d1->parents->next) {
141+
return -1;
142+
}
143+
144+
return 0;
95145
}

0 commit comments

Comments
 (0)