52 #include "net/routing/rpl-classic/rpl-private.h" 55 #define DEBUG DEBUG_NONE 62 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) 63 #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 64 #define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 65 #define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN]) 66 #define UIP_RH_BUF ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 67 #define UIP_RPL_SRH_BUF ((struct uip_rpl_srh_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_RH_LEN]) 68 #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 69 #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 70 #define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 78 uint8_t sender_closer;
80 rpl_parent_t *sender = NULL;
82 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
83 || UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL
84 || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
86 PRINTF(
"RPL: Hop-by-hop extension header has wrong size or type (%u %u %u)\n",
88 UIP_EXT_HDR_OPT_RPL_BUF->opt_type,
89 UIP_EXT_HDR_OPT_RPL_BUF->opt_len);
93 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
94 if(instance == NULL) {
95 PRINTF(
"RPL: Unknown instance: %u\n",
96 UIP_EXT_HDR_OPT_RPL_BUF->instance);
100 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
101 PRINTF(
"RPL: Forward error!\n");
106 if(RPL_IS_STORING(instance)) {
107 route = uip_ds6_route_lookup(&
UIP_IP_BUF->destipaddr);
109 uip_ds6_route_rm(route);
112 RPL_STAT(rpl_stats.forward_errors++);
114 rpl_reset_dio_timer(instance);
119 if(!instance->current_dag->joined) {
120 PRINTF(
"RPL: No DAG in the instance\n");
124 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) {
128 sender_rank =
UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
129 sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER));
131 if(sender != NULL && (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR)) {
134 sender->rank = sender_rank;
135 if(RPL_IS_NON_STORING(instance)) {
139 rpl_select_dag(instance, sender);
143 sender_closer = sender_rank < instance->current_dag->rank;
145 PRINTF(
"RPL: Packet going %s, sender closer %d (%d < %d)\n", down == 1 ?
"down" :
"up",
148 instance->current_dag->rank
151 if((down && !sender_closer) || (!down && sender_closer)) {
152 PRINTF(
"RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n",
153 sender_rank, instance->current_dag->rank,
158 instance->unicast_dio_target = sender;
159 rpl_schedule_unicast_dio_immediately(instance);
161 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) {
162 RPL_STAT(rpl_stats.loop_errors++);
163 PRINTF(
"RPL: Rank error signalled in RPL option!\n");
165 rpl_reset_dio_timer(instance);
168 PRINTF(
"RPL: Single error tolerated\n");
169 RPL_STAT(rpl_stats.loop_warnings++);
170 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
174 PRINTF(
"RPL: Rank OK\n");
181 #if RPL_WITH_NON_STORING 192 while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
193 switch(*uip_next_hdr) {
195 case UIP_PROTO_DESTO:
202 uip_next_hdr = &UIP_EXT_BUF->next;
215 if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
216 && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) ||
217 (dest_node != NULL && root_node != NULL &&
218 dest_node->parent == root_node)) {
224 uip_create_linklocal_prefix(ipaddr);
239 #if RPL_WITH_NON_STORING 247 while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
248 switch(*uip_next_hdr) {
250 case UIP_PROTO_DESTO:
257 uip_next_hdr = &UIP_EXT_BUF->next;
266 if(uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
267 && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) {
269 uint8_t cmpri, cmpre;
273 uint8_t segments_left;
274 uip_ipaddr_t current_dest_addr;
276 segments_left = UIP_RH_BUF->seg_left;
277 ext_len = (UIP_RH_BUF->len * 8) + 8;
278 cmpri = UIP_RPL_SRH_BUF->cmpr >> 4;
279 cmpre = UIP_RPL_SRH_BUF->cmpr & 0x0f;
280 padding = UIP_RPL_SRH_BUF->pad >> 4;
281 path_len = ((ext_len - padding - RPL_RH_LEN - RPL_SRH_LEN - (16 - cmpre)) / (16 - cmpri)) + 1;
284 PRINTF(
"RPL: read SRH, path len %u, segments left %u, Cmpri %u, Cmpre %u, ext len %u (padding %u)\n",
285 path_len, segments_left, cmpri, cmpre, ext_len, padding);
287 if(segments_left == 0) {
290 uint8_t i = path_len - segments_left;
291 uint8_t *addr_ptr = ((uint8_t *)UIP_RH_BUF) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
292 uint8_t cmpr = segments_left == 1 ? cmpre : cmpri;
299 memcpy(((uint8_t *)&
UIP_IP_BUF->destipaddr) + cmpr, addr_ptr, 16 - cmpr);
301 memcpy(addr_ptr, ((uint8_t *)¤t_dest_addr) + cmpr, 16 - cmpr);
304 UIP_RH_BUF->seg_left--;
306 PRINTF(
"RPL: SRH next hop ");
322 count_matching_bytes(
const void *p1,
const void *p2,
size_t n)
325 for(i = 0; i < n; i++) {
326 if(((uint8_t *)p1)[i] != ((uint8_t *)p2)[i]) {
334 insert_srh_header(
void)
340 uint8_t cmpri, cmpre;
347 uip_ipaddr_t node_addr;
349 PRINTF(
"RPL: SRH creating source routing header with destination ");
359 PRINTF(
"RPL: SRH DAG not found\n");
364 if(dest_node == NULL) {
370 if(root_node == NULL) {
371 PRINTF(
"RPL: SRH root node not found\n");
376 PRINTF(
"RPL: SRH no path found to destination\n");
382 node = dest_node->parent;
387 if(node == root_node) {
388 PRINTF(
"RPL: SRH no need to insert SRH\n");
392 while(node != NULL && node != root_node) {
397 cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &
UIP_IP_BUF->destipaddr, 16));
400 PRINTF(
"RPL: SRH Hop ");
401 PRINT6ADDR(&node_addr);
408 ext_len = RPL_RH_LEN + RPL_SRH_LEN
409 + (path_len - 1) * (16 - cmpre)
412 padding = ext_len % 8 == 0 ? 0 : (8 - (ext_len % 8));
415 PRINTF(
"RPL: SRH Path len: %u, ComprI %u, ComprE %u, ext len %u (padding %u)\n",
416 path_len, cmpri, cmpre, ext_len, padding);
420 PRINTF(
"RPL: Packet too long: impossible to add source routing header (%u bytes)\n", ext_len);
434 UIP_RH_BUF->len = (ext_len - 8) / 8;
435 UIP_RH_BUF->routing_type = RPL_RH_TYPE_SRH;
436 UIP_RH_BUF->seg_left = path_len;
439 UIP_RPL_SRH_BUF->cmpr = (cmpri << 4) + cmpre;
440 UIP_RPL_SRH_BUF->pad = padding << 4;
445 hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding;
447 while(node != NULL && node->parent != root_node) {
450 hop_ptr -= (16 - cmpri);
451 memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri);
474 update_hbh_header(
void)
478 int last_uip_ext_len;
479 rpl_parent_t *parent;
483 uip_ext_opt_offset = 2;
486 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
487 || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
489 PRINTF(
"RPL: Hop-by-hop extension header has wrong size (%u %u)\n",
490 UIP_EXT_HDR_OPT_RPL_BUF->opt_len,
495 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
496 if(instance == NULL || !instance->used || !instance->current_dag->joined) {
497 PRINTF(
"RPL: Unable to add/update hop-by-hop extension header: incorrect instance\n");
502 PRINTF(
"RPL: Updating RPL option\n");
504 UIP_EXT_HDR_OPT_RPL_BUF->senderrank =
UIP_HTONS(instance->current_dag->rank);
505 UIP_EXT_HDR_OPT_RPL_BUF->instance = instance->instance_id;
507 if(RPL_IS_STORING(instance)) {
512 if((UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN)) {
513 if(uip_ds6_route_lookup(&
UIP_IP_BUF->destipaddr) == NULL) {
514 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_FWD_ERR;
515 PRINTF(
"RPL forwarding error\n");
518 PRINTF(
"RPL generate No-Path DAO\n");
519 parent = rpl_get_parent((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
521 dao_output_target(parent, &
UIP_IP_BUF->destipaddr, RPL_ZERO_LIFETIME);
530 if(uip_ds6_route_lookup(&
UIP_IP_BUF->destipaddr) == NULL) {
533 UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_DOWN;
534 PRINTF(
"RPL option going up\n");
537 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_DOWN;
538 PRINTF(
"RPL option going down\n");
552 int last_uip_ext_len;
557 uip_ext_opt_offset = 2;
560 PRINTF(
"RPL: Creating hop-by-hop option\n");
562 PRINTF(
"RPL: Packet too long: impossible to add hop-by-hop option\n");
568 memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF,
uip_len - UIP_IPH_LEN);
569 memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
576 UIP_HBHO_BUF->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
577 UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL;
578 UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN;
579 UIP_EXT_HDR_OPT_RPL_BUF->flags = 0;
580 UIP_EXT_HDR_OPT_RPL_BUF->senderrank =
UIP_HTONS(instance->current_dag->rank);
581 UIP_EXT_HDR_OPT_RPL_BUF->instance = instance->instance_id;
589 uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
592 return update_hbh_header();
599 uint8_t rpl_ext_hdr_len;
604 uip_ext_opt_offset = 2;
608 while(uip_next_hdr != NULL) {
609 switch(*uip_next_hdr) {
611 case UIP_PROTO_ROUTING:
612 if((*uip_next_hdr !=
UIP_PROTO_HBHO || UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL)) {
614 *uip_next_hdr = UIP_EXT_BUF->next;
615 rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8;
622 PRINTF(
"RPL: Removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len);
623 memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len,
uip_len - UIP_IPH_LEN);
625 uip_next_hdr = &UIP_EXT_BUF->next;
629 case UIP_PROTO_DESTO:
639 uip_next_hdr = &UIP_EXT_BUF->next;
651 if(default_instance == NULL || default_instance->current_dag == NULL
656 if(default_instance->current_dag->rank ==
ROOT_RANK(default_instance)) {
660 if(rpl_get_dag(&
UIP_IP_BUF->destipaddr) != NULL) {
662 if(RPL_IS_NON_STORING(default_instance)) {
663 return insert_srh_header();
665 return insert_hbh_header(default_instance);
676 return insert_hbh_header(default_instance);
679 return update_hbh_header();
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
#define UIP_IP_BUF
Pointer to IP header.
void rpl_ext_header_remove(void)
Removes all RPL extension headers.
Header for the Contiki/uIP interface.
#define uip_l2_l3_hdr_len
The sums below are quite used in ND.
int rpl_ext_header_hbh_update(int uip_ext_opt_offset)
Process and update the RPL hop-by-hop extension headers of the current uIP packet.
#define ROOT_RANK
Rank of a root node.
uint16_t uip_len
The length of the packet in the uip_buf buffer.
#define UIP_PROTO_HBHO
extension headers types
#define UIP_BUFSIZE
The size of the uIP packet buffer.
int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
Look for next hop from SRH of current uIP packet.
A set of debugging macros for the IP stack
int rpl_ext_header_update(void)
Adds/updates all RPL extension headers to current uIP packet.
Header file for IPv6-related data structures.
An entry in the routing table.
uint8_t uip_ext_opt_offset
length of the header options read
#define UIP_LLH_LEN
The link level header length.
Routing driver header file
#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.
uip_sr_node_t * uip_sr_get_node(void *graph, const uip_ipaddr_t *addr)
Looks up for a source routing node from its IPv6 global address.
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Header file for the uIP TCP/IP stack.
uint8_t uip_ext_len
The length of the extension headers.
uip_ds6_netif_t uip_ds6_if
The single interface.
uint8_t * uip_next_hdr
Type of the next header in IPv6 header or extension headers.
int(* get_sr_node_ipaddr)(uip_ipaddr_t *addr, const uip_sr_node_t *node)
Returns the global IPv6 address of a source routing node.
Header file for the Packet buffer (packetbuf) management
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
int uip_sr_is_addr_reachable(void *graph, const uip_ipaddr_t *addr)
Telle whether an address is reachable, i.e.
A node in a source routing graph, stored at the root and representing all child-parent relationship...
int rpl_ext_header_srh_update(void)
Process and update SRH in-place, i.e.