50 #include "net/rpl/rpl-private.h"
56 #define DEBUG DEBUG_NONE
61 #define RPL_DIO_GROUNDED 0x80
62 #define RPL_DIO_MOP_SHIFT 3
63 #define RPL_DIO_MOP_MASK 0x3c
64 #define RPL_DIO_PREFERENCE_MASK 0x07
66 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
67 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
68 #define UIP_ICMP_PAYLOAD ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len])
70 static void dis_input(
void);
71 static void dio_input(
void);
72 static void dao_input(
void);
73 static void dao_ack_input(
void);
75 static uint8_t dao_sequence;
83 for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
84 state = uip_ds6_if.addr_list[i].state;
85 if(uip_ds6_if.addr_list[i].isused &&
87 if(!uip_is_addr_link_local(&uip_ds6_if.addr_list[i].ipaddr)) {
88 memcpy(addr, &uip_ds6_if.addr_list[i].ipaddr,
sizeof(
uip_ipaddr_t));
97 get32(uint8_t *buffer,
int pos)
99 return (uint32_t)buffer[pos] << 24 | (uint32_t)buffer[pos + 1] << 16 |
100 (uint32_t)buffer[pos + 2] << 8 | buffer[pos + 3];
104 set32(uint8_t *buffer,
int pos, uint32_t value)
106 buffer[pos++] = value >> 24;
107 buffer[pos++] = (value >> 16) & 0xff;
108 buffer[pos++] = (value >> 8) & 0xff;
109 buffer[pos++] = value & 0xff;
113 get16(uint8_t *buffer,
int pos)
115 return (uint16_t)buffer[pos] << 8 | buffer[pos + 1];
119 set16(uint8_t *buffer,
int pos, uint16_t value)
121 buffer[pos++] = value >> 8;
122 buffer[pos++] = value & 0xff;
131 PRINTF(
"RPL: Received a DIS from ");
135 dag = rpl_get_dag(RPL_ANY_INSTANCE);
137 if(uip_is_addr_mcast(&
UIP_IP_BUF->destipaddr)) {
138 PRINTF(
"RPL: Multicast DIS => reset DIO timer\n");
139 rpl_reset_dio_timer(dag, 0);
141 PRINTF(
"RPL: Unicast DIS, reply to sender\n");
150 unsigned char *buffer;
160 buffer = UIP_ICMP_PAYLOAD;
161 buffer[0] = buffer[1] = 0;
164 PRINTF(
"RPL: Sending a DIS\n");
165 uip_create_linklocal_rplnodes_mcast(&tmpaddr);
168 PRINTF(
"RPL: Sending a unicast DIS\n");
176 unsigned char *buffer;
177 uint8_t buffer_length;
185 memset(&dio, 0,
sizeof(dio));
187 dio.dag_intdoubl = DEFAULT_DIO_INTERVAL_DOUBLINGS;
188 dio.dag_intmin = DEFAULT_DIO_INTERVAL_MIN;
189 dio.dag_redund = DEFAULT_DIO_REDUNDANCY;
194 PRINTF(
"RPL: Received a DIO from ");
198 if((nbr = uip_ds6_nbr_lookup(&from)) ==
NULL) {
200 packetbuf_addr(PACKETBUF_ADDR_SENDER),
201 0, NBR_REACHABLE)) !=
NULL) {
203 stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
204 PRINTF(
"RPL: Neighbor added to neighbor cache ");
207 PRINTLLADDR((
uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
211 PRINTF(
"RPL: Neighbor already in neighbor cache\n");
214 buffer_length =
uip_len - uip_l2_l3_icmp_hdr_len;
216 #if RPL_CONF_ADJUST_LLH_LEN
222 buffer = UIP_ICMP_PAYLOAD;
224 dio.instance_id = buffer[i++];
225 dio.version = buffer[i++];
226 dio.rank = get16(buffer, i);
229 PRINTF(
"RPL: Incoming DIO rank %u\n", (
unsigned)dio.rank);
231 dio.grounded = buffer[i] & RPL_DIO_GROUNDED;
232 dio.mop = (buffer[i]& RPL_DIO_MOP_MASK) >> RPL_DIO_MOP_SHIFT;
233 dio.preference = buffer[i++] & RPL_DIO_PREFERENCE_MASK;
235 dio.dtsn = buffer[i++];
239 memcpy(&dio.dag_id, buffer + i,
sizeof(dio.dag_id));
240 i +=
sizeof(dio.dag_id);
243 for(; i < buffer_length; i += len) {
244 subopt_type = buffer[i];
245 if(subopt_type == RPL_OPTION_PAD1) {
249 len = 2 + buffer[i + 1];
252 if(len + i > buffer_length) {
253 PRINTF(
"RPL: Invalid DIO packet\n");
254 RPL_STAT(rpl_stats.malformed_msgs++);
258 PRINTF(
"RPL: DIO option %u, length: %u\n", subopt_type, len - 2);
260 switch(subopt_type) {
261 case RPL_OPTION_DAG_METRIC_CONTAINER:
263 PRINTF(
"RPL: Invalid DAG MC, len = %d\n", len);
264 RPL_STAT(rpl_stats.malformed_msgs++);
268 dio.mc.type = buffer[i + 2];
269 dio.mc.flags = buffer[i + 3] << 1;
270 dio.mc.flags |= buffer[i + 4] >> 7;
271 dio.mc.aggr = (buffer[i + 4] >> 4) & 0x3;
272 dio.mc.prec = buffer[i + 4] & 0xf;
273 dio.mc.length = buffer[i + 5];
275 if(dio.mc.type == RPL_DAG_MC_ETX) {
276 dio.mc.obj.etx = get16(buffer, i + 6);
278 PRINTF(
"RPL: DAG MC: type %u, flags %u, aggr %u, prec %u, length %u, ETX %u\n",
279 (
unsigned)dio.mc.type,
280 (
unsigned)dio.mc.flags,
281 (
unsigned)dio.mc.aggr,
282 (
unsigned)dio.mc.prec,
283 (
unsigned)dio.mc.length,
284 (
unsigned)dio.mc.obj.etx);
285 }
else if(dio.mc.type == RPL_DAG_MC_ENERGY) {
286 dio.mc.obj.energy.flags = buffer[i + 6];
287 dio.mc.obj.energy.energy_est = buffer[i + 7];
289 PRINTF(
"RPL: Unhandled DAG MC type: %u\n", (
unsigned)dio.mc.type);
293 case RPL_OPTION_ROUTE_INFO:
295 PRINTF(
"RPL: Invalid destination prefix option, len = %d\n", len);
296 RPL_STAT(rpl_stats.malformed_msgs++);
301 dio.destination_prefix.length = buffer[i + 2];
302 dio.destination_prefix.flags = buffer[i + 3];
303 dio.destination_prefix.lifetime = get32(buffer, i + 4);
305 if(((dio.destination_prefix.length + 7) / 8) + 8 <= len &&
306 dio.destination_prefix.length <= 128) {
307 PRINTF(
"RPL: Copying destination prefix\n");
308 memcpy(&dio.destination_prefix.prefix, &buffer[i + 8],
309 (dio.destination_prefix.length + 7) / 8);
311 PRINTF(
"RPL: Invalid route infoprefix option, len = %d\n", len);
312 RPL_STAT(rpl_stats.malformed_msgs++);
317 case RPL_OPTION_DAG_CONF:
319 PRINTF(
"RPL: Invalid DAG configuration option, len = %d\n", len);
320 RPL_STAT(rpl_stats.malformed_msgs++);
325 dio.dag_intdoubl = buffer[i + 3];
326 dio.dag_intmin = buffer[i + 4];
327 dio.dag_redund = buffer[i + 5];
328 dio.dag_max_rankinc = get16(buffer, i + 6);
329 dio.dag_min_hoprankinc = get16(buffer, i + 8);
330 dio.ocp = get16(buffer, i + 10);
332 dio.default_lifetime = buffer[i + 13];
333 dio.lifetime_unit = get16(buffer, i + 14);
334 PRINTF(
"RPL: DIO Conf:dbl=%d, min=%d red=%d maxinc=%d mininc=%d ocp=%d d_l=%u l_u=%u\n",
335 dio.dag_intdoubl, dio.dag_intmin, dio.dag_redund,
336 dio.dag_max_rankinc, dio.dag_min_hoprankinc, dio.ocp,
337 dio.default_lifetime, dio.lifetime_unit);
339 case RPL_OPTION_PREFIX_INFO:
341 PRINTF(
"RPL: DAG Prefix info not ok, len != 32\n");
342 RPL_STAT(rpl_stats.malformed_msgs++);
345 dio.prefix_info.length = buffer[i + 2];
346 dio.prefix_info.flags = buffer[i + 3];
349 dio.prefix_info.lifetime = get32(buffer, i + 8);
351 PRINTF(
"RPL: Copying prefix information\n");
352 memcpy(&dio.prefix_info.prefix, &buffer[i + 16], 16);
355 PRINTF(
"RPL: Unsupported suboption type in DIO: %u\n",
356 (
unsigned)subopt_type);
360 rpl_process_dio(&from, &dio);
366 unsigned char *buffer;
373 buffer = UIP_ICMP_PAYLOAD;
374 buffer[pos++] = dag->instance_id;
375 buffer[pos++] = dag->version;
376 set16(buffer, pos, dag->rank);
381 buffer[pos] |= RPL_DIO_GROUNDED;
384 buffer[pos++] = dag->mop << RPL_DIO_MOP_SHIFT;
385 buffer[pos++] = ++dag->dtsn_out;
391 memcpy(buffer + pos, &dag->dag_id,
sizeof(dag->dag_id));
394 if(dag->mc.type != RPL_DAG_MC_NONE) {
395 dag->of->update_metric_container(dag);
397 buffer[pos++] = RPL_OPTION_DAG_METRIC_CONTAINER;
399 buffer[pos++] = dag->mc.type;
400 buffer[pos++] = dag->mc.flags >> 1;
401 buffer[pos] = (dag->mc.flags & 1) << 7;
402 buffer[pos++] |= (dag->mc.aggr << 4) | dag->mc.prec;
404 if(dag->mc.type == RPL_DAG_MC_ETX) {
406 set16(buffer, pos, dag->mc.obj.etx);
408 }
else if(dag->mc.type == RPL_DAG_MC_ENERGY) {
410 buffer[pos++] = dag->mc.obj.energy.flags;
411 buffer[pos++] = dag->mc.obj.energy.energy_est;
413 PRINTF(
"RPL: Unable to send DIO because of unhandled DAG MC type %u\n",
414 (
unsigned)dag->mc.type);
420 buffer[pos++] = RPL_OPTION_DAG_CONF;
423 buffer[pos++] = dag->dio_intdoubl;
424 buffer[pos++] = dag->dio_intmin;
425 buffer[pos++] = dag->dio_redundancy;
426 set16(buffer, pos, dag->max_rankinc);
428 set16(buffer, pos, dag->min_hoprankinc);
431 set16(buffer, pos, dag->of->ocp);
434 buffer[pos++] = dag->default_lifetime;
435 set16(buffer, pos, dag->lifetime_unit);
439 if(dag->prefix_info.length > 0) {
440 buffer[pos++] = RPL_OPTION_PREFIX_INFO;
442 buffer[pos++] = dag->prefix_info.length;
443 buffer[pos++] = dag->prefix_info.flags;
444 set32(buffer, pos, dag->prefix_info.lifetime);
446 set32(buffer, pos, dag->prefix_info.lifetime);
448 memset(&buffer[pos], 0, 4);
450 memcpy(&buffer[pos], &dag->prefix_info.prefix, 16);
452 PRINTF(
"RPL: Sending prefix info in DIO for ");
453 PRINT6ADDR(&dag->prefix_info.prefix);
456 PRINTF(
"RPL: No prefix to announce (len %d)\n",
457 dag->prefix_info.length);
461 if(uc_addr ==
NULL) {
462 PRINTF(
"RPL: Sending a multicast-DIO with rank %u\n",
463 (
unsigned)dag->rank);
464 uip_create_linklocal_rplnodes_mcast(&addr);
467 PRINTF(
"RPL: Sending unicast-DIO with rank %u to ",
468 (
unsigned)dag->rank);
480 unsigned char *buffer;
483 rpl_lifetime_t lifetime;
488 uint8_t pathsequence;
491 uint8_t buffer_length;
503 PRINTF(
"RPL: Received a DAO from ");
504 PRINT6ADDR(&dao_sender_addr);
507 buffer = UIP_ICMP_PAYLOAD;
508 buffer_length =
uip_len - uip_l2_l3_icmp_hdr_len;
509 #if RPL_CONF_ADJUST_LLH_LEN
514 instance_id = buffer[pos++];
516 dag = rpl_get_dag(instance_id);
518 PRINTF(
"RPL: Ignoring a DAO for a different RPL instance (%u)\n",
523 lifetime = dag->default_lifetime;
525 flags = buffer[pos++];
528 sequence = buffer[pos++];
531 if(flags & RPL_DAO_D_FLAG) {
539 for(; i < buffer_length; i += len) {
540 subopt_type = buffer[i];
541 if(subopt_type == RPL_OPTION_PAD1) {
545 len = 2 + buffer[i + 1];
548 switch(subopt_type) {
549 case RPL_OPTION_TARGET:
551 prefixlen = buffer[i + 3];
552 memset(&prefix, 0,
sizeof(prefix));
553 memcpy(&prefix, buffer + i + 4, (prefixlen + 7) / CHAR_BIT);
555 case RPL_OPTION_TRANSIT:
557 pathcontrol = buffer[i + 3];
558 pathsequence = buffer[i + 4];
559 lifetime = buffer[i + 5];
565 PRINTF(
"RPL: DAO lifetime: %u, prefix length: %u prefix: ",
566 (
unsigned)lifetime, (
unsigned)prefixlen);
570 rep = uip_ds6_route_lookup(&prefix);
572 if(lifetime == ZERO_LIFETIME) {
574 if(rep !=
NULL && rep->state.saved_lifetime == 0) {
575 PRINTF(
"RPL: Setting expiration timer for prefix ");
578 rep->state.saved_lifetime = rep->state.lifetime;
579 rep->state.lifetime = DAO_EXPIRATION_TIMEOUT;
584 learned_from = uip_is_addr_mcast(&dao_sender_addr) ?
585 RPL_ROUTE_FROM_MULTICAST_DAO : RPL_ROUTE_FROM_UNICAST_DAO;
587 if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
589 p = rpl_find_parent(dag, &dao_sender_addr);
590 if(p !=
NULL && DAG_RANK(p->rank, dag) < DAG_RANK(dag->rank, dag)) {
591 PRINTF(
"RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n",
592 DAG_RANK(p->rank, dag), DAG_RANK(dag->rank, dag));
593 p->rank = INFINITE_RANK;
600 rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr);
602 RPL_STAT(rpl_stats.mem_overflows++);
603 PRINTF(
"RPL: Could not add a route after receiving a DAO\n");
608 rep->state.lifetime = RPL_LIFETIME(dag, lifetime);
609 rep->state.learned_from = learned_from;
611 if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
612 if(dag->preferred_parent) {
613 PRINTF(
"RPL: Forwarding DAO to parent ");
614 PRINT6ADDR(&dag->preferred_parent->addr);
618 }
else if(flags & RPL_DAO_K_FLAG) {
619 dao_ack_output(dag, &dao_sender_addr, sequence);
625 dao_output(rpl_parent_t *n, rpl_lifetime_t lifetime)
628 unsigned char *buffer;
635 if(get_global_addr(&prefix) == 0) {
636 PRINTF(
"RPL: No global address set for this node - suppressing DAO\n");
641 dag = rpl_get_dag(RPL_ANY_INSTANCE);
643 PRINTF(
"RPL: Did not join a DAG before sending DAO\n");
650 buffer = UIP_ICMP_PAYLOAD;
655 buffer[pos++] = dag->instance_id;
657 buffer[pos++] = RPL_DAO_K_FLAG;
662 buffer[pos++] = dao_sequence & 0xff;
665 prefixlen =
sizeof(prefix) * CHAR_BIT;
666 buffer[pos++] = RPL_OPTION_TARGET;
667 buffer[pos++] = 2 + ((prefixlen + 7) / CHAR_BIT);
669 buffer[pos++] = prefixlen;
670 memcpy(buffer + pos, &prefix, (prefixlen + 7) / CHAR_BIT);
671 pos += ((prefixlen + 7) / CHAR_BIT);
674 buffer[pos++] = RPL_OPTION_TRANSIT;
679 buffer[pos++] = lifetime;
682 uip_create_linklocal_rplnodes_mcast(&addr);
687 PRINTF(
"RPL: Sending DAO with prefix ");
691 PRINT6ADDR(&n->addr);
693 PRINTF(
"multicast address");
703 unsigned char *buffer;
704 uint8_t buffer_length;
709 buffer = UIP_ICMP_PAYLOAD;
710 buffer_length =
uip_len - uip_l2_l3_icmp_hdr_len;
711 #if RPL_CONF_ADJUST_LLH_LEN
715 instance_id = buffer[0];
716 sequence = buffer[2];
719 PRINTF(
"RPL: Received a DAO ACK with sequence number %d and status %d from ",
726 dao_ack_output(rpl_dag_t *dag,
uip_ipaddr_t *dest, uint8_t sequence)
728 unsigned char *buffer;
730 PRINTF(
"RPL: Sending a DAO ACK with sequence number %d to ", sequence);
734 buffer = UIP_ICMP_PAYLOAD;
736 buffer[0] = dag->instance_id;
738 buffer[2] = sequence;
747 PRINTF(
"Received an RPL control message\n");
758 case RPL_CODE_DAO_ACK:
762 PRINTF(
"RPL: received an unknown ICMP6 code (%u)\n",
UIP_ICMP_BUF->icode);