47 #include "net/ipv6/uip-ds6.h"
48 #include "net/rpl/rpl-private.h"
50 #define DEBUG DEBUG_NONE
57 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
58 #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
59 #define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len])
60 #define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN])
61 #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
62 #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
63 #define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
71 uint8_t sender_closer;
74 if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
75 PRINTF(
"RPL: Bad header option! (wrong length)\n");
79 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
80 if(instance ==
NULL) {
81 PRINTF(
"RPL: Unknown instance: %u\n",
82 UIP_EXT_HDR_OPT_RPL_BUF->instance);
86 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
87 PRINTF(
"RPL: Forward error!\n");
100 PRINTF(
"RPL: initiate global repair\n");
101 rpl_repair_root(instance->instance_id);
106 UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_FWD_ERR;
110 if(!instance->current_dag->joined) {
111 PRINTF(
"RPL: No DAG in the instance\n");
116 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) {
120 sender_closer = UIP_EXT_HDR_OPT_RPL_BUF->senderrank < instance->current_dag->rank;
122 PRINTF(
"RPL: Packet going %s, sender closer %d (%d < %d)\n", down == 1 ?
"down" :
"up",
124 UIP_EXT_HDR_OPT_RPL_BUF->senderrank,
125 instance->current_dag->rank
128 if((down && !sender_closer) || (!down && sender_closer)) {
129 PRINTF(
"RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n",
130 UIP_EXT_HDR_OPT_RPL_BUF->senderrank, instance->current_dag->rank,
132 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) {
133 PRINTF(
"RPL: Rank error signalled in RPL option!\n");
135 rpl_reset_dio_timer(instance);
139 PRINTF(
"RPL: Single error tolerated\n");
140 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
144 PRINTF(
"RPL: Rank OK\n");
150 set_rpl_opt(
unsigned uip_ext_opt_offset)
154 memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF,
uip_len - UIP_IPH_LEN);
155 memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
158 UIP_HBHO_BUF->len = RPL_HOP_BY_HOP_LEN - 8;
159 UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL;
160 UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN;
161 UIP_EXT_HDR_OPT_RPL_BUF->flags = 0;
162 UIP_EXT_HDR_OPT_RPL_BUF->instance = 0;
163 UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0;
173 rpl_update_header_empty(
void)
177 int last_uip_ext_len;
181 uip_ext_opt_offset = 2;
183 PRINTF(
"RPL: Verifying the presence of the RPL header option\n");
187 if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) {
188 PRINTF(
"RPL: Non RPL Hop-by-hop options support not implemented\n");
192 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
193 if(instance ==
NULL || !instance->used || !instance->current_dag->joined) {
194 PRINTF(
"RPL: Unable to add hop-by-hop extension header: incorrect instance\n");
199 PRINTF(
"RPL: No hop-by-hop option found, creating it\n");
201 PRINTF(
"RPL: Packet too long: impossible to add hop-by-hop option\n");
205 set_rpl_opt(uip_ext_opt_offset);
206 uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
210 switch(UIP_EXT_HDR_OPT_BUF->type) {
211 case UIP_EXT_HDR_OPT_RPL:
212 PRINTF(
"RPL: Updating RPL option\n");
213 UIP_EXT_HDR_OPT_RPL_BUF->senderrank = instance->current_dag->rank;
219 if((UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN)) {
221 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_FWD_ERR;
222 PRINTF(
"RPL forwarding error\n");
231 UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_DOWN;
232 PRINTF(
"RPL option going up\n");
235 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_DOWN;
236 PRINTF(
"RPL option going down\n");
243 PRINTF(
"RPL: Multi Hop-by-hop options not implemented\n");
250 rpl_update_header_final(uip_ipaddr_t *addr)
252 rpl_parent_t *parent;
254 int last_uip_ext_len;
258 uip_ext_opt_offset = 2;
261 if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) {
262 PRINTF(
"RPL: Non RPL Hop-by-hop options support not implemented\n");
267 if(UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) {
268 if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank == 0) {
269 PRINTF(
"RPL: Updating RPL option\n");
270 if(default_instance ==
NULL || !default_instance->used || !default_instance->current_dag->joined) {
271 PRINTF(
"RPL: Unable to add hop-by-hop extension header: incorrect default instance\n");
274 parent = rpl_find_parent(default_instance->current_dag, addr);
275 if(parent ==
NULL || parent != parent->dag->preferred_parent) {
276 UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN;
278 UIP_EXT_HDR_OPT_RPL_BUF->instance = default_instance->instance_id;
279 UIP_EXT_HDR_OPT_RPL_BUF->senderrank = default_instance->current_dag->rank;
288 rpl_remove_header(
void)
294 PRINTF(
"RPL: Verifying the presence of the RPL header option\n");
297 PRINTF(
"RPL: Removing the RPL header option\n");
300 uip_len -= UIP_HBHO_BUF->len + 8;
305 memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF,
uip_len - UIP_IPH_LEN);
308 PRINTF(
"RPL: No hop-by-hop Option found\n");
313 rpl_invert_header(
void)
316 uint8_t last_uip_ext_len;
320 uip_ext_opt_offset = 2;
322 PRINTF(
"RPL: Verifying the presence of the RPL header option\n");
327 PRINTF(
"RPL: No hop-by-hop Option found\n");
332 switch (UIP_EXT_HDR_OPT_BUF->type) {
333 case UIP_EXT_HDR_OPT_RPL:
334 PRINTF(
"RPL: Updating RPL option (switching direction)\n");
335 UIP_EXT_HDR_OPT_RPL_BUF->flags &= RPL_HDR_OPT_DOWN;
336 UIP_EXT_HDR_OPT_RPL_BUF->flags ^= RPL_HDR_OPT_DOWN;
337 UIP_EXT_HDR_OPT_RPL_BUF->senderrank = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank;
339 return RPL_HOP_BY_HOP_LEN;
341 PRINTF(
"RPL: Multi Hop-by-hop options not implemented\n");
348 rpl_insert_header(
void)
351 if(default_instance !=
NULL) {
352 uip_ext_opt_offset = 2;
353 if(UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) {
354 rpl_update_header_empty();