50 #include "net/rpl/rpl-private.h"
54 #define DEBUG DEBUG_NONE
61 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
62 #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
63 #define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len])
64 #define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN])
65 #define UIP_RH_BUF ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len])
66 #define UIP_RPL_SRH_BUF ((struct uip_rpl_srh_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_RH_LEN])
67 #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
68 #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
69 #define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
74 rpl_instance_t *instance;
77 uint8_t sender_closer;
79 rpl_parent_t *sender =
NULL;
81 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)) {
82 PRINTF(
"RPL: Hop-by-hop extension header has wrong size\n");
86 if(UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL) {
87 PRINTF(
"RPL: Non RPL Hop-by-hop option\n");
91 if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
92 PRINTF(
"RPL: Bad header option! (wrong length)\n");
96 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
97 if(instance ==
NULL) {
98 PRINTF(
"RPL: Unknown instance: %u\n",
99 UIP_EXT_HDR_OPT_RPL_BUF->instance);
103 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
104 PRINTF(
"RPL: Forward error!\n");
109 if(RPL_IS_STORING(instance)) {
110 route = uip_ds6_route_lookup(&
UIP_IP_BUF->destipaddr);
112 uip_ds6_route_rm(route);
115 RPL_STAT(rpl_stats.forward_errors++);
117 rpl_reset_dio_timer(instance);
122 if(!instance->current_dag->joined) {
123 PRINTF(
"RPL: No DAG in the instance\n");
128 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) {
132 sender_rank =
UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
133 sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER));
135 if(sender !=
NULL && (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR)) {
138 sender->rank = sender_rank;
139 if(RPL_IS_NON_STORING(instance)) {
143 rpl_select_dag(instance, sender);
147 sender_closer = sender_rank < instance->current_dag->rank;
149 PRINTF(
"RPL: Packet going %s, sender closer %d (%d < %d)\n", down == 1 ?
"down" :
"up",
152 instance->current_dag->rank
155 if((down && !sender_closer) || (!down && sender_closer)) {
156 PRINTF(
"RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n",
157 sender_rank, instance->current_dag->rank,
162 instance->unicast_dio_target = sender;
163 rpl_schedule_unicast_dio_immediately(instance);
165 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) {
166 RPL_STAT(rpl_stats.loop_errors++);
167 PRINTF(
"RPL: Rank error signalled in RPL option!\n");
169 rpl_reset_dio_timer(instance);
172 PRINTF(
"RPL: Single error tolerated\n");
173 RPL_STAT(rpl_stats.loop_warnings++);
174 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
178 PRINTF(
"RPL: Rank OK\n");
182 #if RPL_WITH_NON_STORING
184 rpl_srh_get_next_hop(uip_ipaddr_t *
ipaddr)
189 rpl_ns_node_t *dest_node;
190 rpl_ns_node_t *root_node;
196 while(uip_next_hdr !=
NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
197 switch(*uip_next_hdr) {
200 case UIP_PROTO_ICMP6:
205 case UIP_PROTO_DESTO:
211 uip_next_hdr = &UIP_EXT_BUF->next;
219 root_node = rpl_ns_get_node(dag, &dag->dag_id);
220 dest_node = rpl_ns_get_node(dag, &
UIP_IP_BUF->destipaddr);
222 if((uip_next_hdr !=
NULL && *uip_next_hdr == UIP_PROTO_ROUTING
223 && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) ||
224 (dest_node !=
NULL && root_node !=
NULL &&
225 dest_node->parent == root_node)) {
231 uip_create_linklocal_prefix(ipaddr);
241 rpl_process_srh_header(
void)
250 while(uip_next_hdr !=
NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
251 switch(*uip_next_hdr) {
254 case UIP_PROTO_ICMP6:
259 case UIP_PROTO_DESTO:
265 uip_next_hdr = &UIP_EXT_BUF->next;
272 if(uip_next_hdr !=
NULL && *uip_next_hdr == UIP_PROTO_ROUTING
273 && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) {
275 uint8_t cmpri, cmpre;
279 uint8_t segments_left;
280 uip_ipaddr_t current_dest_addr;
282 segments_left = UIP_RH_BUF->seg_left;
283 ext_len = (UIP_RH_BUF->len * 8) + 8;
284 cmpri = UIP_RPL_SRH_BUF->cmpr >> 4;
285 cmpre = UIP_RPL_SRH_BUF->cmpr & 0x0f;
286 padding = UIP_RPL_SRH_BUF->pad >> 4;
287 path_len = ((ext_len - padding - RPL_RH_LEN - RPL_SRH_LEN - (16 - cmpre)) / (16 - cmpri)) + 1;
290 PRINTF(
"RPL: read SRH, path len %u, segments left %u, Cmpri %u, Cmpre %u, ext len %u (padding %u)\n",
291 path_len, segments_left, cmpri, cmpre, ext_len, padding);
293 if(segments_left == 0) {
296 uint8_t i = path_len - segments_left;
297 uint8_t *addr_ptr = ((uint8_t *)UIP_RH_BUF) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
298 uint8_t cmpr = segments_left == 1 ? cmpre : cmpri;
305 memcpy(((uint8_t *)&
UIP_IP_BUF->destipaddr) + cmpr, addr_ptr, 16 - cmpr);
307 memcpy(addr_ptr, ((uint8_t *)¤t_dest_addr) + cmpr, 16 - cmpr);
310 UIP_RH_BUF->seg_left--;
312 PRINTF(
"RPL: SRH next hop ");
325 count_matching_bytes(
const void *p1,
const void *p2,
size_t n)
328 for(i = 0; i < n; i++) {
329 if(((uint8_t *)p1)[i] != ((uint8_t *)p2)[i]) {
337 insert_srh_header(
void)
343 uint8_t cmpri, cmpre;
346 rpl_ns_node_t *dest_node;
347 rpl_ns_node_t *root_node;
350 uip_ipaddr_t node_addr;
352 PRINTF(
"RPL: SRH creating source routing header with destination ");
362 PRINTF(
"RPL: SRH DAG not found\n");
366 dest_node = rpl_ns_get_node(dag, &
UIP_IP_BUF->destipaddr);
367 if(dest_node ==
NULL) {
372 root_node = rpl_ns_get_node(dag, &dag->dag_id);
373 if(root_node ==
NULL) {
374 PRINTF(
"RPL: SRH root node not found\n");
378 if(!rpl_ns_is_node_reachable(dag, &
UIP_IP_BUF->destipaddr)) {
379 PRINTF(
"RPL: SRH no path found to destination\n");
385 node = dest_node->parent;
390 if(node == root_node) {
391 PRINTF(
"RPL: SRH no need to insert SRH\n");
395 while(node !=
NULL && node != root_node) {
397 rpl_ns_get_node_global_addr(&node_addr, node);
400 cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &
UIP_IP_BUF->destipaddr, 16));
403 PRINTF(
"RPL: SRH Hop ");
404 PRINT6ADDR(&node_addr);
411 ext_len = RPL_RH_LEN + RPL_SRH_LEN
412 + (path_len - 1) * (16 - cmpre)
415 padding = ext_len % 8 == 0 ? 0 : (8 - (ext_len % 8));
418 PRINTF(
"RPL: SRH Path len: %u, ComprI %u, ComprE %u, ext len %u (padding %u)\n",
419 path_len, cmpri, cmpre, ext_len, padding);
423 PRINTF(
"RPL: Packet too long: impossible to add source routing header (%u bytes)\n", ext_len);
437 UIP_RH_BUF->len = (ext_len - 8) / 8;
438 UIP_RH_BUF->routing_type = RPL_RH_TYPE_SRH;
439 UIP_RH_BUF->seg_left = path_len;
442 UIP_RPL_SRH_BUF->cmpr = (cmpri << 4) + cmpre;
443 UIP_RPL_SRH_BUF->pad = padding << 4;
448 hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding;
450 while(node !=
NULL && node->parent != root_node) {
451 rpl_ns_get_node_global_addr(&node_addr, node);
453 hop_ptr -= (16 - cmpri);
454 memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri);
460 rpl_ns_get_node_global_addr(&node_addr, node);
476 int insert_srh_header(
void);
480 update_hbh_header(
void)
482 rpl_instance_t *instance;
484 int last_uip_ext_len;
485 rpl_parent_t *parent;
489 uip_ext_opt_offset = 2;
491 PRINTF(
"RPL: Verifying the presence of the RPL header option\n");
495 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)) {
496 PRINTF(
"RPL: Hop-by-hop extension header has wrong size\n");
500 if(UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL) {
501 PRINTF(
"RPL: Non RPL Hop-by-hop option support not implemented\n");
505 if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
506 PRINTF(
"RPL: RPL Hop-by-hop option has wrong length\n");
510 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
511 if(instance ==
NULL || !instance->used || !instance->current_dag->joined) {
512 PRINTF(
"RPL: Unable to add hop-by-hop extension header: incorrect instance\n");
517 PRINTF(
"RPL: No hop-by-hop option found\n");
521 switch(UIP_EXT_HDR_OPT_BUF->type) {
522 case UIP_EXT_HDR_OPT_RPL:
523 PRINTF(
"RPL: Updating RPL option\n");
524 UIP_EXT_HDR_OPT_RPL_BUF->senderrank =
UIP_HTONS(instance->current_dag->rank);
526 if(RPL_IS_STORING(instance)) {
531 if((UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN)) {
533 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_FWD_ERR;
534 PRINTF(
"RPL forwarding error\n");
537 PRINTF(
"RPL generate No-Path DAO\n");
538 parent = rpl_get_parent((
uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
540 dao_output_target(parent, &
UIP_IP_BUF->destipaddr, RPL_ZERO_LIFETIME);
552 UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_DOWN;
553 PRINTF(
"RPL option going up\n");
556 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_DOWN;
557 PRINTF(
"RPL option going down\n");
565 PRINTF(
"RPL: Multi Hop-by-hop options not implemented\n");
572 insert_hbh_header(
void)
575 int last_uip_ext_len;
580 uip_ext_opt_offset = 2;
583 PRINTF(
"RPL: Creating hop-by-hop option\n");
585 PRINTF(
"RPL: Packet too long: impossible to add hop-by-hop option\n");
591 memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF,
uip_len - UIP_IPH_LEN);
592 memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
599 UIP_HBHO_BUF->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
600 UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL;
601 UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN;
602 UIP_EXT_HDR_OPT_RPL_BUF->flags = 0;
603 UIP_EXT_HDR_OPT_RPL_BUF->instance = 0;
604 UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0;
612 uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
617 rpl_finalize_header(uip_ipaddr_t *
addr)
619 rpl_parent_t *parent;
621 int last_uip_ext_len;
625 uip_ext_opt_offset = 2;
628 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)) {
629 PRINTF(
"RPL: Non RPL Hop-by-hop options support not implemented\n");
634 if(UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) {
635 if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank == 0) {
636 PRINTF(
"RPL: Updating RPL option\n");
637 if(default_instance ==
NULL || !default_instance->used || !default_instance->current_dag->joined) {
638 PRINTF(
"RPL: Unable to add hop-by-hop extension header: incorrect default instance\n");
641 parent = rpl_find_parent(default_instance->current_dag, addr);
642 if(parent ==
NULL || parent != parent->dag->preferred_parent) {
643 UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN;
645 UIP_EXT_HDR_OPT_RPL_BUF->instance = default_instance->instance_id;
646 UIP_EXT_HDR_OPT_RPL_BUF->senderrank =
UIP_HTONS(default_instance->current_dag->rank);
654 rpl_remove_header(
void)
657 uint8_t rpl_ext_hdr_len;
663 PRINTF(
"RPL: Verifying the presence of RPL extension headers\n");
666 while(uip_next_hdr !=
NULL) {
667 switch(*uip_next_hdr) {
670 case UIP_PROTO_ICMP6:
674 case UIP_PROTO_ROUTING:
676 *uip_next_hdr = UIP_EXT_BUF->next;
677 rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8;
684 PRINTF(
"RPL: Removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len);
685 memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len,
uip_len - UIP_IPH_LEN);
692 uip_next_hdr = &UIP_EXT_BUF->next;
699 rpl_insert_header(
void)
701 if(default_instance ==
NULL || default_instance->current_dag ==
NULL
706 if(RPL_IS_STORING(default_instance)) {
710 if(RPL_IS_NON_STORING(default_instance)) {
711 if(default_instance->current_dag !=
NULL) {
712 if(default_instance->current_dag->rank == ROOT_RANK(default_instance)) {
722 rpl_update_header(
void)
724 if(default_instance ==
NULL) {
728 if(default_instance->current_dag !=
NULL) {
729 if(default_instance->current_dag->rank == ROOT_RANK(default_instance)) {
733 if(RPL_IS_NON_STORING(default_instance)) {
734 return insert_srh_header();
736 return insert_hbh_header();
739 return update_hbh_header();
uip_len
The length of the packet in the uip_buf buffer.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Header file for IPv6-related data structures.
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define UIP_IP_BUF
Pointer to IP header.
Header file for the Rime buffer (packetbuf) management
uint8_t uip_ext_opt_offset
length of the header options read
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 3513 a is of type uip_ipaddr_t*
static uip_ds6_route_t * route
The next route to use.
Header for the Contiki/uIP interface.
uint8_t * uip_next_hdr
Type of the next header in IPv6 header or extension headers.
uint8_t uip_ext_len
The length of the extension headers.
#define NULL
The null pointer.
Header file for the uIP TCP/IP stack.
#define UIP_PROTO_HBHO
extension headers types
A set of debugging macros for the IP stack
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
RPL non-storing mode specific functions.
#define uip_l2_l3_hdr_len
The sums below are quite used in ND.
#define UIP_BUFSIZE
The size of the uIP packet buffer.
An entry in the routing table.