52 #include "net/routing/rpl-classic/rpl-private.h" 57 #define LOG_MODULE "RPL" 58 #define LOG_LEVEL LOG_LEVEL_RPL 64 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) 65 #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 66 #define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 67 #define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN]) 68 #define UIP_RH_BUF ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 69 #define UIP_RPL_SRH_BUF ((struct uip_rpl_srh_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_RH_LEN]) 70 #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 71 #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 72 #define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 80 uint8_t sender_closer;
82 rpl_parent_t *sender = NULL;
84 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
85 || UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL
86 || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
88 LOG_ERR(
"Hop-by-hop extension header has wrong size or type (%u %u %u)\n",
90 UIP_EXT_HDR_OPT_RPL_BUF->opt_type,
91 UIP_EXT_HDR_OPT_RPL_BUF->opt_len);
95 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
96 if(instance == NULL) {
97 LOG_ERR(
"Unknown instance: %u\n",
98 UIP_EXT_HDR_OPT_RPL_BUF->instance);
102 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
103 LOG_ERR(
"Forward error!\n");
108 if(RPL_IS_STORING(instance)) {
109 route = uip_ds6_route_lookup(&
UIP_IP_BUF->destipaddr);
111 uip_ds6_route_rm(route);
114 RPL_STAT(rpl_stats.forward_errors++);
116 rpl_reset_dio_timer(instance);
121 if(!instance->current_dag->joined) {
122 LOG_ERR(
"No DAG in the instance\n");
126 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) {
130 sender_rank =
UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
131 sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER));
133 if(sender != NULL && (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR)) {
136 sender->rank = sender_rank;
137 if(RPL_IS_NON_STORING(instance)) {
141 rpl_select_dag(instance, sender);
145 sender_closer = sender_rank < instance->current_dag->rank;
147 LOG_DBG(
"Packet going %s, sender closer %d (%d < %d)\n", down == 1 ?
"down" :
"up",
150 instance->current_dag->rank
153 if((down && !sender_closer) || (!down && sender_closer)) {
154 LOG_WARN(
"Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n",
155 sender_rank, instance->current_dag->rank,
160 instance->unicast_dio_target = sender;
161 rpl_schedule_unicast_dio_immediately(instance);
163 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) {
164 RPL_STAT(rpl_stats.loop_errors++);
165 LOG_ERR(
" Rank error signalled in RPL option!\n");
167 rpl_reset_dio_timer(instance);
170 LOG_WARN(
"Single error tolerated\n");
171 RPL_STAT(rpl_stats.loop_warnings++);
172 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
176 LOG_DBG(
"Rank OK\n");
183 #if RPL_WITH_NON_STORING 194 while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
195 switch(*uip_next_hdr) {
197 case UIP_PROTO_DESTO:
204 uip_next_hdr = &UIP_EXT_BUF->next;
217 if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
218 && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) ||
219 (dest_node != NULL && root_node != NULL &&
220 dest_node->parent == root_node)) {
226 uip_create_linklocal_prefix(ipaddr);
241 #if RPL_WITH_NON_STORING 249 while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
250 switch(*uip_next_hdr) {
252 case UIP_PROTO_DESTO:
259 uip_next_hdr = &UIP_EXT_BUF->next;
268 if(uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
269 && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) {
271 uint8_t cmpri, cmpre;
275 uint8_t segments_left;
276 uip_ipaddr_t current_dest_addr;
278 segments_left = UIP_RH_BUF->seg_left;
279 ext_len = (UIP_RH_BUF->len * 8) + 8;
280 cmpri = UIP_RPL_SRH_BUF->cmpr >> 4;
281 cmpre = UIP_RPL_SRH_BUF->cmpr & 0x0f;
282 padding = UIP_RPL_SRH_BUF->pad >> 4;
283 path_len = ((ext_len - padding - RPL_RH_LEN - RPL_SRH_LEN - (16 - cmpre)) / (16 - cmpri)) + 1;
286 LOG_DBG(
"read SRH, path len %u, segments left %u, Cmpri %u, Cmpre %u, ext len %u (padding %u)\n",
287 path_len, segments_left, cmpri, cmpre, ext_len, padding);
289 if(segments_left == 0) {
292 uint8_t i = path_len - segments_left;
293 uint8_t *addr_ptr = ((uint8_t *)UIP_RH_BUF) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
294 uint8_t cmpr = segments_left == 1 ? cmpre : cmpri;
301 memcpy(((uint8_t *)&
UIP_IP_BUF->destipaddr) + cmpr, addr_ptr, 16 - cmpr);
303 memcpy(addr_ptr, ((uint8_t *)¤t_dest_addr) + cmpr, 16 - cmpr);
306 UIP_RH_BUF->seg_left--;
308 LOG_INFO(
"SRH next hop ");
324 count_matching_bytes(
const void *p1,
const void *p2,
size_t n)
327 for(i = 0; i < n; i++) {
328 if(((uint8_t *)p1)[i] != ((uint8_t *)p2)[i]) {
336 insert_srh_header(
void)
342 uint8_t cmpri, cmpre;
349 uip_ipaddr_t node_addr;
351 LOG_INFO(
"SRH creating source routing header with destination ");
361 LOG_ERR(
"SRH DAG not found\n");
366 if(dest_node == NULL) {
372 if(root_node == NULL) {
373 LOG_ERR(
"SRH root node not found\n");
378 LOG_ERR(
"SRH no path found to destination\n");
384 node = dest_node->parent;
389 if(node == root_node) {
390 LOG_DBG(
"SRH no need to insert SRH\n");
394 while(node != NULL && node != root_node) {
399 cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &
UIP_IP_BUF->destipaddr, 16));
403 LOG_DBG_6ADDR(&node_addr);
410 ext_len = RPL_RH_LEN + RPL_SRH_LEN
411 + (path_len - 1) * (16 - cmpre)
414 padding = ext_len % 8 == 0 ? 0 : (8 - (ext_len % 8));
417 LOG_DBG(
"SRH Path len: %u, ComprI %u, ComprE %u, ext len %u (padding %u)\n",
418 path_len, cmpri, cmpre, ext_len, padding);
422 LOG_ERR(
"Packet too long: impossible to add source routing header (%u bytes)\n", ext_len);
436 UIP_RH_BUF->len = (ext_len - 8) / 8;
437 UIP_RH_BUF->routing_type = RPL_RH_TYPE_SRH;
438 UIP_RH_BUF->seg_left = path_len;
441 UIP_RPL_SRH_BUF->cmpr = (cmpri << 4) + cmpre;
442 UIP_RPL_SRH_BUF->pad = padding << 4;
447 hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding;
449 while(node != NULL && node->parent != root_node) {
452 hop_ptr -= (16 - cmpri);
453 memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri);
476 update_hbh_header(
void)
480 int last_uip_ext_len;
481 rpl_parent_t *parent;
485 uip_ext_opt_offset = 2;
488 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
489 || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
491 LOG_ERR(
"Hop-by-hop extension header has wrong size (%u %u)\n",
492 UIP_EXT_HDR_OPT_RPL_BUF->opt_len,
497 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
498 if(instance == NULL || !instance->used || !instance->current_dag->joined) {
499 LOG_ERR(
"Unable to add/update hop-by-hop extension header: incorrect instance\n");
504 LOG_INFO(
"Updating RPL option\n");
506 UIP_EXT_HDR_OPT_RPL_BUF->senderrank =
UIP_HTONS(instance->current_dag->rank);
507 UIP_EXT_HDR_OPT_RPL_BUF->instance = instance->instance_id;
509 if(RPL_IS_STORING(instance)) {
514 if((UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN)) {
515 if(uip_ds6_route_lookup(&
UIP_IP_BUF->destipaddr) == NULL) {
516 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_FWD_ERR;
517 LOG_WARN(
"RPL forwarding error\n");
520 LOG_WARN(
"RPL generate No-Path DAO\n");
521 parent = rpl_get_parent((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
523 dao_output_target(parent, &
UIP_IP_BUF->destipaddr, RPL_ZERO_LIFETIME);
532 if(uip_ds6_route_lookup(&
UIP_IP_BUF->destipaddr) == NULL) {
535 UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_DOWN;
536 LOG_DBG(
"RPL option going up\n");
539 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_DOWN;
540 LOG_DBG(
"RPL option going down\n");
554 int last_uip_ext_len;
559 uip_ext_opt_offset = 2;
562 LOG_DBG(
"Creating hop-by-hop option\n");
564 LOG_ERR(
"Packet too long: impossible to add hop-by-hop option\n");
570 memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF,
uip_len - UIP_IPH_LEN);
571 memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
578 UIP_HBHO_BUF->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
579 UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL;
580 UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN;
581 UIP_EXT_HDR_OPT_RPL_BUF->flags = 0;
582 UIP_EXT_HDR_OPT_RPL_BUF->senderrank =
UIP_HTONS(instance->current_dag->rank);
583 UIP_EXT_HDR_OPT_RPL_BUF->instance = instance->instance_id;
591 uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
594 return update_hbh_header();
601 uint8_t rpl_ext_hdr_len;
606 uip_ext_opt_offset = 2;
610 while(uip_next_hdr != NULL) {
611 switch(*uip_next_hdr) {
613 case UIP_PROTO_ROUTING:
614 if((*uip_next_hdr !=
UIP_PROTO_HBHO || UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL)) {
616 *uip_next_hdr = UIP_EXT_BUF->next;
617 rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8;
624 LOG_DBG(
"Removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len);
625 memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len,
uip_len - UIP_IPH_LEN);
627 uip_next_hdr = &UIP_EXT_BUF->next;
631 case UIP_PROTO_DESTO:
641 uip_next_hdr = &UIP_EXT_BUF->next;
653 if(default_instance == NULL || default_instance->current_dag == NULL
658 if(default_instance->current_dag->rank ==
ROOT_RANK(default_instance)) {
662 if(rpl_get_dag(&
UIP_IP_BUF->destipaddr) != NULL) {
664 if(RPL_IS_NON_STORING(default_instance)) {
665 return insert_srh_header();
667 return insert_hbh_header(default_instance);
678 return insert_hbh_header(default_instance);
681 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.
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.
Header file for the logging system
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.