47 #include "net/routing/rpl-lite/rpl.h" 53 #define LOG_MODULE "RPL" 54 #define LOG_LEVEL LOG_LEVEL_RPL 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_RH_BUF ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 62 #define UIP_RPL_SRH_BUF ((struct uip_rpl_srh_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_RH_LEN]) 63 #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 64 #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 65 #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 while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
81 switch(*uip_next_hdr) {
88 uip_next_hdr = &UIP_EXT_BUF->next;
104 if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
105 && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) ||
106 (dest_node != NULL && root_node != NULL &&
107 dest_node->parent == root_node)) {
113 uip_create_linklocal_prefix(ipaddr);
118 LOG_DBG(
"no SRH found\n");
128 uint8_t cmpri, cmpre;
132 uint8_t segments_left;
133 uip_ipaddr_t current_dest_addr;
139 while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
140 switch(*uip_next_hdr) {
142 case UIP_PROTO_DESTO:
147 uip_next_hdr = &UIP_EXT_BUF->next;
156 if(uip_next_hdr == NULL || *uip_next_hdr != UIP_PROTO_ROUTING
157 || UIP_RH_BUF->routing_type != RPL_RH_TYPE_SRH) {
158 LOG_INFO(
"SRH not found\n");
164 segments_left = UIP_RH_BUF->seg_left;
165 ext_len = (UIP_RH_BUF->len * 8) + 8;
166 cmpri = UIP_RPL_SRH_BUF->cmpr >> 4;
167 cmpre = UIP_RPL_SRH_BUF->cmpr & 0x0f;
168 padding = UIP_RPL_SRH_BUF->pad >> 4;
169 path_len = ((ext_len - padding - RPL_RH_LEN - RPL_SRH_LEN - (16 - cmpre)) / (16 - cmpri)) + 1;
172 LOG_INFO(
"read SRH, path len %u, segments left %u, Cmpri %u, Cmpre %u, ext len %u (padding %u)\n",
173 path_len, segments_left, cmpri, cmpre, ext_len, padding);
176 if(segments_left == 0) {
179 uint8_t i = path_len - segments_left;
180 uint8_t *addr_ptr = ((uint8_t *)UIP_RH_BUF) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
181 uint8_t cmpr = segments_left == 1 ? cmpre : cmpri;
188 memcpy(((uint8_t *)&
UIP_IP_BUF->destipaddr) + cmpr, addr_ptr, 16 - cmpr);
190 memcpy(addr_ptr, ((uint8_t *)¤t_dest_addr) + cmpr, 16 - cmpr);
193 UIP_RH_BUF->seg_left--;
195 LOG_INFO(
"SRH next hop ");
207 count_matching_bytes(
const void *p1,
const void *p2,
size_t n)
210 for(i = 0; i < n; i++) {
211 if(((uint8_t *)p1)[i] != ((uint8_t *)p2)[i]) {
223 insert_srh_header(
void)
229 uint8_t cmpri, cmpre;
235 uip_ipaddr_t node_addr;
237 LOG_INFO(
"SRH creating source routing header with destination ");
247 LOG_INFO(
"SRH destination not in our DAG, skip SRH insertion\n");
252 if(dest_node == NULL) {
254 LOG_INFO(
"SRH node not found, skip SRH insertion\n");
259 if(root_node == NULL) {
260 LOG_ERR(
"SRH root node not found\n");
265 LOG_ERR(
"SRH no path found to destination\n");
271 node = dest_node->parent;
280 while(node != NULL && node != root_node) {
285 cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &
UIP_IP_BUF->destipaddr, 16));
288 LOG_INFO(
"SRH Hop ");
289 LOG_INFO_6ADDR(&node_addr);
296 ext_len = RPL_RH_LEN + RPL_SRH_LEN
297 + (path_len - 1) * (16 - cmpre)
300 padding = ext_len % 8 == 0 ? 0 : (8 - (ext_len % 8));
303 LOG_INFO(
"SRH path len: %u, ComprI %u, ComprE %u, ext len %u (padding %u)\n",
304 path_len, cmpri, cmpre, ext_len, padding);
308 LOG_ERR(
"packet too long: impossible to add source routing header (%u bytes)\n", ext_len);
322 UIP_RH_BUF->len = (ext_len - 8) / 8;
323 UIP_RH_BUF->routing_type = RPL_RH_TYPE_SRH;
324 UIP_RH_BUF->seg_left = path_len;
327 UIP_RPL_SRH_BUF->cmpr = (cmpri << 4) + cmpre;
328 UIP_RPL_SRH_BUF->pad = padding << 4;
333 hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding;
335 while(node != NULL && node->parent != root_node) {
338 hop_ptr -= (16 - cmpri);
339 memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri);
365 int rank_error_signaled;
367 uint16_t sender_rank;
368 uint8_t sender_closer;
370 uint8_t opt_type = UIP_EXT_HDR_OPT_RPL_BUF->opt_type;
371 uint8_t opt_len = UIP_EXT_HDR_OPT_RPL_BUF->opt_len;
373 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
374 || opt_type != UIP_EXT_HDR_OPT_RPL
375 || opt_len != RPL_HDR_OPT_LEN) {
376 LOG_ERR(
"hop-by-hop extension header has wrong size or type (%u %u %u)\n",
377 UIP_HBHO_BUF->len, opt_type, opt_len);
381 if(!curr_instance.used || curr_instance.instance_id != UIP_EXT_HDR_OPT_RPL_BUF->instance) {
382 LOG_ERR(
"unknown instance: %u\n",
383 UIP_EXT_HDR_OPT_RPL_BUF->instance);
387 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
388 LOG_ERR(
"forward error!\n");
392 down = (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) ? 1 : 0;
393 sender_rank =
UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
394 sender = nbr_table_get_from_lladdr(rpl_neighbors, packetbuf_addr(PACKETBUF_ADDR_SENDER));
395 rank_error_signaled = (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) ? 1 : 0;
396 sender_closer = sender_rank < curr_instance.dag.rank;
397 loop_detected = (down && !sender_closer) || (!down && sender_closer);
399 LOG_INFO(
"ext hdr: packet from ");
403 LOG_INFO_(
" going %s, sender closer %d (%d < %d), rank error %u, loop detected %u\n",
404 down == 1 ?
"down" :
"up", sender_closer, sender_rank,
405 curr_instance.dag.rank, rank_error_signaled, loop_detected);
409 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
412 return rpl_process_hbh(sender, sender_rank, loop_detected, rank_error_signaled);
419 update_hbh_header(
void)
422 int last_uip_ext_len;
426 uip_ext_opt_offset = 2;
429 if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
430 || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
432 LOG_ERR(
"hop-by-hop extension header has wrong size (%u %u)\n",
437 if(!curr_instance.used || curr_instance.instance_id != UIP_EXT_HDR_OPT_RPL_BUF->instance) {
438 LOG_ERR(
"unable to add/update hop-by-hop extension header: incorrect instance\n");
444 UIP_EXT_HDR_OPT_RPL_BUF->senderrank =
UIP_HTONS(curr_instance.dag.rank);
445 UIP_EXT_HDR_OPT_RPL_BUF->instance = curr_instance.instance_id;
457 insert_hbh_header(
void)
460 int last_uip_ext_len;
465 uip_ext_opt_offset = 2;
468 LOG_INFO(
"creating hop-by-hop option\n");
470 LOG_ERR(
"packet too long: impossible to add hop-by-hop option\n");
476 memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF,
uip_len - UIP_IPH_LEN);
477 memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
484 UIP_HBHO_BUF->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
485 UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL;
486 UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN;
487 UIP_EXT_HDR_OPT_RPL_BUF->flags = 0;
488 UIP_EXT_HDR_OPT_RPL_BUF->senderrank =
UIP_HTONS(curr_instance.dag.rank);
489 UIP_EXT_HDR_OPT_RPL_BUF->instance = curr_instance.instance_id;
497 uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
500 return update_hbh_header();
506 if(!curr_instance.used
517 return insert_srh_header();
523 return insert_hbh_header();
526 return update_hbh_header();
535 uint8_t rpl_ext_hdr_len;
540 uip_ext_opt_offset = 2;
544 while(uip_next_hdr != NULL) {
545 switch(*uip_next_hdr) {
547 case UIP_PROTO_ROUTING:
548 if((*uip_next_hdr !=
UIP_PROTO_HBHO || UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL)) {
550 *uip_next_hdr = UIP_EXT_BUF->next;
551 rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8;
558 LOG_INFO(
"removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len);
559 memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len,
uip_len - UIP_IPH_LEN);
561 uip_next_hdr = &UIP_EXT_BUF->next;
565 case UIP_PROTO_DESTO:
575 uip_next_hdr = &UIP_EXT_BUF->next;
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.
#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.
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_is_addr_in_our_dag(const uip_ipaddr_t *addr)
Tells whether a given global IPv6 address is in our current DAG.
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.
int rpl_dag_root_is_root(void)
Tells whether we are DAG root or not.
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.
All information related to a RPL neighbor.
#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.
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 rpl_process_hbh(rpl_nbr_t *sender, uint16_t sender_rank, int loop_detected, int rank_error_signaled)
Processes Hop-by-Hop (HBH) Extension Header of a packet currently being forwrded. ...
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.