Contiki-NG
sicslowpan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * 6lowpan implementation (RFC4944 and draft-ietf-6lowpan-hc-06)
36  *
37  * \author Adam Dunkels <adam@sics.se>
38  * \author Nicolas Tsiftes <nvt@sics.se>
39  * \author Niclas Finne <nfi@sics.se>
40  * \author Mathilde Durvy <mdurvy@cisco.com>
41  * \author Julien Abeille <jabeille@cisco.com>
42  * \author Joakim Eriksson <joakime@sics.se>
43  * \author Joel Hoglund <joel@sics.se>
44  */
45 
46 /**
47  * \addtogroup sicslowpan
48  * \ingroup uip
49  * @{
50  */
51 
52 /**
53  * FOR HC-06 COMPLIANCE TODO:
54  * -Add compression options to UDP, currently only supports
55  * both ports compressed or both ports elided
56  *
57  * -Verify TC/FL compression works
58  *
59  * -Add stateless multicast option
60  */
61 
62 #include <string.h>
63 
64 #include "contiki.h"
65 #include "dev/watchdog.h"
66 #include "net/link-stats.h"
67 #include "net/ipv6/uipopt.h"
68 #include "net/ipv6/tcpip.h"
69 #include "net/ipv6/uip.h"
70 #include "net/ipv6/uip-ds6.h"
71 #include "net/ipv6/uipbuf.h"
72 #include "net/ipv6/sicslowpan.h"
73 #include "net/netstack.h"
74 #include "net/packetbuf.h"
75 #include "net/queuebuf.h"
76 
77 #include "net/routing/routing.h"
78 
79 /* Log configuration */
80 #include "sys/log.h"
81 #define LOG_MODULE "6LoWPAN"
82 #define LOG_LEVEL LOG_LEVEL_6LOWPAN
83 
84 #define GET16(ptr,index) (((uint16_t)((ptr)[index] << 8)) | ((ptr)[(index) + 1]))
85 #define SET16(ptr,index,value) do { \
86  (ptr)[index] = ((value) >> 8) & 0xff; \
87  (ptr)[index + 1] = (value) & 0xff; \
88 } while(0)
89 
90 /** \name Pointers in the packetbuf buffer
91  * @{
92  */
93 #define PACKETBUF_FRAG_PTR (packetbuf_ptr)
94 #define PACKETBUF_FRAG_DISPATCH_SIZE 0 /* 16 bit */
95 #define PACKETBUF_FRAG_TAG 2 /* 16 bit */
96 #define PACKETBUF_FRAG_OFFSET 4 /* 8 bit */
97 
98 /* define the buffer as a byte array */
99 #define PACKETBUF_IPHC_BUF ((uint8_t *)(packetbuf_ptr + packetbuf_hdr_len))
100 #define PACKETBUF_PAYLOAD_END ((uint8_t *)(packetbuf_ptr + mac_max_payload))
101 
102 #define PACKETBUF_6LO_PTR (packetbuf_ptr + packetbuf_hdr_len)
103 #define PACKETBUF_6LO_DISPATCH 0 /* 8 bit */
104 #define PACKETBUF_6LO_ENCODING 1 /* 8 bit */
105 #define PACKETBUF_6LO_TTL 2 /* 8 bit */
106 
107 #define PACKETBUF_6LO_HC_UDP_PTR (packetbuf_ptr + packetbuf_hdr_len)
108 #define PACKETBUF_6LO_HC_UDP_DISPATCH 0 /* 8 bit */
109 #define PACKETBUF_6LO_HC_UDP_HC1_ENCODING 1 /* 8 bit */
110 #define PACKETBUF_6LO_HC_UDP_UDP_ENCODING 2 /* 8 bit */
111 #define PACKETBUF_6LO_HC_UDP_TTL 3 /* 8 bit */
112 #define PACKETBUF_6LO_HC_UDP_PORTS 4 /* 8 bit */
113 #define PACKETBUF_6LO_HC_UDP_CHKSUM 5 /* 16 bit */
114 
115 /** \name Pointers in the sicslowpan and uip buffer
116  * @{
117  */
118 
119 /* NOTE: In the multiple-reassembly context there is only room for the header / first fragment */
120 #define SICSLOWPAN_IP_BUF(buf) ((struct uip_ip_hdr *)buf)
121 #define SICSLOWPAN_UDP_BUF(buf) ((struct uip_udp_hdr *)&buf[UIP_IPH_LEN])
122 #define SICSLOWPAN_IPPAYLOAD_BUF(buf) (&buf[UIP_IPH_LEN])
123 
124 
125 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
126 #define UIP_UDP_BUF(p) ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN + p])
127 #define UIP_TCP_BUF ((struct uip_tcp_hdr *)&uip_buf[UIP_LLIPH_LEN])
128 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN])
129 #define UIP_IPPAYLOAD_BUF(pos) (&uip_buf[UIP_LLIPH_LEN + pos])
130 
131 /** @} */
132 
133 
134 /** \brief Maximum available size for frame headers,
135  link layer security-related overhead, as well as
136  6LoWPAN payload. */
137 #ifdef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
138 #define MAC_MAX_PAYLOAD SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
139 #else /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
140 #define MAC_MAX_PAYLOAD (127 - 2)
141 #endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
142 
143 /** \brief Maximum size of a frame header. This value is
144  * used in case framer returns an error */
145 #ifdef SICSLOWPAN_CONF_MAC_MAX_HEADER
146 #define MAC_MAX_HEADER SICSLOWPAN_CONF_MAC_MAX_HEADER
147 #else /* SICSLOWPAN_CONF_MAC_MAX_HEADER */
148 #define MAC_MAX_HEADER 21
149 #endif /* SICSLOWPAN_CONF_MAC_MAX_HEADER */
150 
151 /* set this to zero if not compressing EXT_HDR - for backwards compatibility */
152 #ifdef SICSLOWPAN_CONF_COMPRESS_EXT_HDR
153 #define COMPRESS_EXT_HDR SICSLOWPAN_CONF_COMPRESS_EXT_HDR
154 #else
155 /* Compressing on by default - turn off to be compatible with older versions */
156 #define COMPRESS_EXT_HDR 1
157 #endif
158 
159 #if COMPRESS_EXT_HDR
160 #define IS_COMPRESSABLE_PROTO(x) (x == UIP_PROTO_UDP \
161  || x == UIP_PROTO_HBHO \
162  || x == UIP_PROTO_DESTO \
163  || x == UIP_PROTO_ROUTING \
164  || x == UIP_PROTO_FRAG)
165 #else
166 #define IS_COMPRESSABLE_PROTO(x) (x == UIP_PROTO_UDP)
167 #endif /* COMPRESS_EXT_HDR */
168 
169 /** \name General variables
170  * @{
171  */
172 
173 /**
174  * A pointer to the packetbuf buffer.
175  * We initialize it to the beginning of the packetbuf buffer, then
176  * access different fields by updating the offset packetbuf_hdr_len.
177  */
178 static uint8_t *packetbuf_ptr;
179 
180 /**
181  * packetbuf_hdr_len is the total length of (the processed) 6lowpan headers
182  * (fragment headers, IPV6 or HC1, HC2, and HC1 and HC2 non compressed
183  * fields).
184  */
185 static uint8_t packetbuf_hdr_len;
186 
187 /**
188  * The length of the payload in the Packetbuf buffer.
189  * The payload is what comes after the compressed or uncompressed
190  * headers (can be the IP payload if the IP header only is compressed
191  * or the UDP payload if the UDP header is also compressed)
192  */
194 
195 /**
196  * uncomp_hdr_len is the length of the headers before compression (if HC2
197  * is used this includes the UDP header in addition to the IP header).
198  */
199 static uint8_t uncomp_hdr_len;
200 
201 /**
202  * mac_max_payload is the maimum payload space on the MAC frame.
203  */
204 static int mac_max_payload;
205 
206 /**
207  * The current page (RFC 4944)
208  */
209 static uint8_t curr_page;
210 
211 /**
212  * the result of the last transmitted fragment
213  */
214 static int last_tx_status;
215 /** @} */
216 
217 
218 static int last_rssi;
219 
220 /* ----------------------------------------------------------------- */
221 /* Support for reassembling multiple packets */
222 /* ----------------------------------------------------------------- */
223 
224 #if SICSLOWPAN_CONF_FRAG
225 static uint16_t my_tag;
226 
227 /** The total length of the IPv6 packet in the sicslowpan_buf. */
228 
229 /* This needs to be defined in NBR / Nodes depending on available RAM */
230 /* and expected reassembly requirements */
231 #ifdef SICSLOWPAN_CONF_FRAGMENT_BUFFERS
232 #define SICSLOWPAN_FRAGMENT_BUFFERS SICSLOWPAN_CONF_FRAGMENT_BUFFERS
233 #else
234 #define SICSLOWPAN_FRAGMENT_BUFFERS 12
235 #endif
236 
237 /* REASS_CONTEXTS corresponds to the number of simultaneous
238  * reassemblies that can be made. NOTE: the first buffer for each
239  * reassembly is stored in the context since it can be larger than the
240  * rest of the fragments due to header compression.
241  **/
242 #ifdef SICSLOWPAN_CONF_REASS_CONTEXTS
243 #define SICSLOWPAN_REASS_CONTEXTS SICSLOWPAN_CONF_REASS_CONTEXTS
244 #else
245 #define SICSLOWPAN_REASS_CONTEXTS 2
246 #endif
247 
248 /* The size of each fragment (IP payload) for the 6lowpan fragmentation */
249 #ifdef SICSLOWPAN_CONF_FRAGMENT_SIZE
250 #define SICSLOWPAN_FRAGMENT_SIZE SICSLOWPAN_CONF_FRAGMENT_SIZE
251 #else
252 /* The default fragment size (110 bytes for 127-2 bytes frames) */
253 #define SICSLOWPAN_FRAGMENT_SIZE (MAC_MAX_PAYLOAD - 15)
254 #endif
255 
256 /* Assuming that the worst growth for uncompression is 38 bytes */
257 #define SICSLOWPAN_FIRST_FRAGMENT_SIZE (SICSLOWPAN_FRAGMENT_SIZE + 38)
258 
259 /* all information needed for reassembly */
260 struct sicslowpan_frag_info {
261  /** When reassembling, the source address of the fragments being merged */
262  linkaddr_t sender;
263  /** The destination address of the fragments being merged */
264  linkaddr_t receiver;
265  /** When reassembling, the tag in the fragments being merged. */
266  uint16_t tag;
267  /** Total length of the fragmented packet */
268  uint16_t len;
269  /** Current length of reassembled fragments */
270  uint16_t reassembled_len;
271  /** Reassembly %process %timer. */
272  struct timer reass_timer;
273 
274  /** Fragment size of first fragment */
275  uint16_t first_frag_len;
276  /** First fragment - needs a larger buffer since the size is uncompressed size
277  and we need to know total size to know when we have received last fragment. */
278  uint8_t first_frag[SICSLOWPAN_FIRST_FRAGMENT_SIZE];
279 };
280 
281 static struct sicslowpan_frag_info frag_info[SICSLOWPAN_REASS_CONTEXTS];
282 
283 struct sicslowpan_frag_buf {
284  /* the index of the frag_info */
285  uint8_t index;
286  /* Fragment offset */
287  uint8_t offset;
288  /* Length of this fragment (if zero this buffer is not allocated) */
289  uint8_t len;
290  uint8_t data[SICSLOWPAN_FRAGMENT_SIZE];
291 };
292 
293 static struct sicslowpan_frag_buf frag_buf[SICSLOWPAN_FRAGMENT_BUFFERS];
294 
295 /*---------------------------------------------------------------------------*/
296 static int
297 clear_fragments(uint8_t frag_info_index)
298 {
299  int i, clear_count;
300  clear_count = 0;
301  frag_info[frag_info_index].len = 0;
302  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
303  if(frag_buf[i].len > 0 && frag_buf[i].index == frag_info_index) {
304  /* deallocate the buffer */
305  frag_buf[i].len = 0;
306  clear_count++;
307  }
308  }
309  return clear_count;
310 }
311 /*---------------------------------------------------------------------------*/
312 static int
313 timeout_fragments(int not_context)
314 {
315  int i;
316  int count = 0;
317  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
318  if(frag_info[i].len > 0 && i != not_context &&
319  timer_expired(&frag_info[i].reass_timer)) {
320  /* This context can be freed */
321  count += clear_fragments(i);
322  }
323  }
324  return count;
325 }
326 /*---------------------------------------------------------------------------*/
327 static int
328 store_fragment(uint8_t index, uint8_t offset)
329 {
330  int i;
331  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
332  if(frag_buf[i].len == 0) {
333  /* copy over the data from packetbuf into the fragment buffer and store offset and len */
334  frag_buf[i].offset = offset; /* frag offset */
335  frag_buf[i].len = packetbuf_datalen() - packetbuf_hdr_len;
336  frag_buf[i].index = index;
337  memcpy(frag_buf[i].data, packetbuf_ptr + packetbuf_hdr_len,
339  /* return the length of the stored fragment */
340  return frag_buf[i].len;
341  }
342  }
343  /* failed */
344  return -1;
345 }
346 /*---------------------------------------------------------------------------*/
347 /* add a new fragment to the buffer */
348 static int8_t
349 add_fragment(uint16_t tag, uint16_t frag_size, uint8_t offset)
350 {
351  int i;
352  int len;
353  int8_t found = -1;
354 
355  if(offset == 0) {
356  /* This is a first fragment - check if we can add this */
357  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
358  /* clear all fragment info with expired timer to free all fragment buffers */
359  if(frag_info[i].len > 0 && timer_expired(&frag_info[i].reass_timer)) {
360  clear_fragments(i);
361  }
362 
363  /* We use len as indication on used or not used */
364  if(found < 0 && frag_info[i].len == 0) {
365  /* We remember the first free fragment info but must continue
366  the loop to free any other expired fragment buffers. */
367  found = i;
368  }
369  }
370 
371  if(found < 0) {
372  LOG_WARN("reassembly: failed to store new fragment session - tag: %d\n", tag);
373  return -1;
374  }
375 
376  /* Found a free fragment info to store data in */
377  frag_info[found].len = frag_size;
378  frag_info[found].tag = tag;
379  linkaddr_copy(&frag_info[found].sender,
380  packetbuf_addr(PACKETBUF_ADDR_SENDER));
381  timer_set(&frag_info[found].reass_timer, SICSLOWPAN_REASS_MAXAGE * CLOCK_SECOND / 16);
382  /* first fragment can not be stored immediately but is moved into
383  the buffer while uncompressing */
384  return found;
385  }
386 
387  /* This is a N-fragment - should find the info */
388  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
389  if(frag_info[i].tag == tag && frag_info[i].len > 0 &&
390  linkaddr_cmp(&frag_info[i].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
391  /* Tag and Sender match - this must be the correct info to store in */
392  found = i;
393  break;
394  }
395  }
396 
397  if(found < 0) {
398  /* no entry found for storing the new fragment */
399  LOG_WARN("reassembly: failed to store N-fragment - could not find session - tag: %d offset: %d\n", tag, offset);
400  return -1;
401  }
402 
403  /* i is the index of the reassembly context */
404  len = store_fragment(i, offset);
405  if(len < 0 && timeout_fragments(i) > 0) {
406  len = store_fragment(i, offset);
407  }
408  if(len > 0) {
409  frag_info[i].reassembled_len += len;
410  return i;
411  } else {
412  /* should we also clear all fragments since we failed to store
413  this fragment? */
414  LOG_WARN("reassembly: failed to store fragment - packet reassembly will fail tag:%d l\n", frag_info[i].tag);
415  return -1;
416  }
417 }
418 /*---------------------------------------------------------------------------*/
419 /* Copy all the fragments that are associated with a specific context
420  into uip */
421 static void
422 copy_frags2uip(int context)
423 {
424  int i;
425 
426  /* Copy from the fragment context info buffer first */
427  memcpy((uint8_t *)UIP_IP_BUF, (uint8_t *)frag_info[context].first_frag,
428  frag_info[context].first_frag_len);
429  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
430  /* And also copy all matching fragments */
431  if(frag_buf[i].len > 0 && frag_buf[i].index == context) {
432  memcpy((uint8_t *)UIP_IP_BUF + (uint16_t)(frag_buf[i].offset << 3),
433  (uint8_t *)frag_buf[i].data, frag_buf[i].len);
434  }
435  }
436  /* deallocate all the fragments for this context */
437  clear_fragments(context);
438 }
439 #endif /* SICSLOWPAN_CONF_FRAG */
440 
441 /* -------------------------------------------------------------------------- */
442 
443 /*-------------------------------------------------------------------------*/
444 /* Basic netstack sniffer */
445 /*-------------------------------------------------------------------------*/
446 static struct netstack_sniffer *callback = NULL;
447 
448 void
449 netstack_sniffer_add(struct netstack_sniffer *s)
450 {
451  callback = s;
452 }
453 
454 void
455 netstack_sniffer_remove(struct netstack_sniffer *s)
456 {
457  callback = NULL;
458 }
459 
460 static void
461 set_packet_attrs(void)
462 {
463  int c = 0;
464  /* set protocol in NETWORK_ID */
465  packetbuf_set_attr(PACKETBUF_ATTR_NETWORK_ID, UIP_IP_BUF->proto);
466 
467  /* assign values to the channel attribute (port or type + code) */
468  if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
469  c = UIP_UDP_BUF(0)->srcport;
470  if(UIP_UDP_BUF(0)->destport < c) {
471  c = UIP_UDP_BUF(0)->destport;
472  }
473  } else if(UIP_IP_BUF->proto == UIP_PROTO_TCP) {
474  c = UIP_TCP_BUF->srcport;
475  if(UIP_TCP_BUF->destport < c) {
476  c = UIP_TCP_BUF->destport;
477  }
478  } else if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6) {
479  c = UIP_ICMP_BUF->type << 8 | UIP_ICMP_BUF->icode;
480  }
481 
482  packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, c);
483 
484 /* if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { */
485 /* own = 1; */
486 /* } */
487 
488 }
489 
490 
491 
492 #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC
493 /** \name variables specific to HC06 and more recent versions
494  * @{
495  */
496 
497 /** Addresses contexts for IPHC. */
498 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
499 static struct sicslowpan_addr_context
500 addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
501 #endif
502 
503 /** pointer to an address context. */
505 
506 /** pointer to the byte where to write next inline field. */
507 static uint8_t *hc06_ptr;
508 
509 /* Uncompression of linklocal */
510 /* 0 -> 16 bytes from packet */
511 /* 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet */
512 /* 2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet */
513 /* 3 -> 2 bytes from prefix - infer 8 bytes from lladdr */
514 /* NOTE: => the uncompress function does change 0xf to 0x10 */
515 /* NOTE: 0x00 => no-autoconfig => unspecified */
516 const uint8_t unc_llconf[] = {0x0f,0x28,0x22,0x20};
517 
518 /* Uncompression of ctx-based */
519 /* 0 -> 0 bits from packet [unspecified / reserved] */
520 /* 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet */
521 /* 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX + 2 from packet */
522 /* 3 -> 8 bytes from prefix - infer 8 bytes from lladdr */
523 const uint8_t unc_ctxconf[] = {0x00,0x88,0x82,0x80};
524 
525 /* Uncompression of ctx-based */
526 /* 0 -> 0 bits from packet */
527 /* 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet */
528 /* 2 -> 2 bytes from prefix - zeroes + 3 from packet */
529 /* 3 -> 2 bytes from prefix - infer 1 bytes from lladdr */
530 const uint8_t unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
531 
532 /* Link local prefix */
533 const uint8_t llprefix[] = {0xfe, 0x80};
534 
535 /* TTL uncompression values */
536 static const uint8_t ttl_values[] = {0, 1, 64, 255};
537 
538 /*--------------------------------------------------------------------*/
539 /** \name IPHC related functions
540  * @{ */
541 /*--------------------------------------------------------------------*/
542 /** \brief find the context corresponding to prefix ipaddr */
543 static struct sicslowpan_addr_context*
545 {
546 /* Remove code to avoid warnings and save flash if no context is used */
547 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
548  int i;
549  for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
550  if((addr_contexts[i].used == 1) &&
551  uip_ipaddr_prefixcmp(&addr_contexts[i].prefix, ipaddr, 64)) {
552  return &addr_contexts[i];
553  }
554  }
555 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
556  return NULL;
557 }
558 /*--------------------------------------------------------------------*/
559 /** \brief find the context with the given number */
560 static struct sicslowpan_addr_context*
562 {
563 /* Remove code to avoid warnings and save flash if no context is used */
564 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
565  int i;
566  for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
567  if((addr_contexts[i].used == 1) &&
568  addr_contexts[i].number == number) {
569  return &addr_contexts[i];
570  }
571  }
572 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
573  return NULL;
574 }
575 /*--------------------------------------------------------------------*/
576 static uint8_t
577 compress_addr_64(uint8_t bitpos, uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
578 {
579  if(uip_is_addr_mac_addr_based(ipaddr, lladdr)) {
580  return 3 << bitpos; /* 0-bits */
582  /* compress IID to 16 bits xxxx::0000:00ff:fe00:XXXX */
583  memcpy(hc06_ptr, &ipaddr->u16[7], 2);
584  hc06_ptr += 2;
585  return 2 << bitpos; /* 16-bits */
586  } else {
587  /* do not compress IID => xxxx::IID */
588  memcpy(hc06_ptr, &ipaddr->u16[4], 8);
589  hc06_ptr += 8;
590  return 1 << bitpos; /* 64-bits */
591  }
592 }
593 
594 /*-------------------------------------------------------------------- */
595 /* Uncompress addresses based on a prefix and a postfix with zeroes in
596  * between. If the postfix is zero in length it will use the link address
597  * to configure the IP address (autoconf style).
598  * pref_post_count takes a byte where the first nibble specify prefix count
599  * and the second postfix count (NOTE: 15/0xf => 16 bytes copy).
600  */
601 static void
602 uncompress_addr(uip_ipaddr_t *ipaddr, uint8_t const prefix[],
603  uint8_t pref_post_count, uip_lladdr_t *lladdr)
604 {
605  uint8_t prefcount = pref_post_count >> 4;
606  uint8_t postcount = pref_post_count & 0x0f;
607  /* full nibble 15 => 16 */
608  prefcount = prefcount == 15 ? 16 : prefcount;
609  postcount = postcount == 15 ? 16 : postcount;
610 
611  LOG_DBG("uncompression: address %d %d", prefcount, postcount);
612 
613  if(prefcount > 0) {
614  memcpy(ipaddr, prefix, prefcount);
615  }
616  if(prefcount + postcount < 16) {
617  memset(&ipaddr->u8[prefcount], 0, 16 - (prefcount + postcount));
618  }
619  if(postcount > 0) {
620  memcpy(&ipaddr->u8[16 - postcount], hc06_ptr, postcount);
621  if(postcount == 2 && prefcount < 11) {
622  /* 16 bits uncompression => 0000:00ff:fe00:XXXX */
623  ipaddr->u8[11] = 0xff;
624  ipaddr->u8[12] = 0xfe;
625  }
626  hc06_ptr += postcount;
627  } else if (prefcount > 0) {
628  /* no IID based configuration if no prefix and no data => unspec */
629  uip_ds6_set_addr_iid(ipaddr, lladdr);
630  }
631 
632  LOG_DBG_6ADDR(ipaddr);
633  LOG_DBG_("\n");
634 }
635 
636 /*--------------------------------------------------------------------*/
637 /**
638  * \brief Compress IP/UDP header
639  *
640  * This function is called by the 6lowpan code to create a compressed
641  * 6lowpan packet in the packetbuf buffer from a full IPv6 packet in the
642  * uip_buf buffer.
643  *
644  *
645  * IPHC (RFC 6282)\n
646  * http://tools.ietf.org/html/
647  *
648  * \note We do not support ISA100_UDP header compression
649  *
650  * For LOWPAN_UDP compression, we either compress both ports or none.
651  * General format with LOWPAN_UDP compression is
652  * \verbatim
653  * 1 2 3
654  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
655  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
656  * |0|1|1|TF |N|HLI|C|S|SAM|M|D|DAM| SCI | DCI | comp. IPv6 hdr|
657  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
658  * | compressed IPv6 fields ..... |
659  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
660  * | LOWPAN_UDP | non compressed UDP fields ... |
661  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
662  * | L4 data ... |
663  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
664  * \endverbatim
665  * \note The context number 00 is reserved for the link local prefix.
666  * For unicast addresses, if we cannot compress the prefix, we neither
667  * compress the IID.
668  * \param link_destaddr L2 destination address, needed to compress IP
669  * dest
670  * \return 1 if success, else 0
671  */
672 static int
673 compress_hdr_iphc(linkaddr_t *link_destaddr)
674 {
675  uint8_t tmp, iphc0, iphc1, *next_hdr, *next_nhc;
676  int ext_hdr_len;
677  struct uip_udp_hdr *udp_buf;
678 
679  if(LOG_DBG_ENABLED) {
680  uint16_t ndx;
681  LOG_DBG("compression: before (%d): ", UIP_IP_BUF->len[1]);
682  for(ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
683  uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
684  LOG_DBG_("%02x", data);
685  }
686  LOG_DBG_("\n");
687  }
688 
689 /* Macro used only internally, during header compression. Checks if there
690  * is sufficient space in packetbuf before writing any further. */
691 #define CHECK_BUFFER_SPACE(writelen) do { \
692  if(hc06_ptr + (writelen) >= PACKETBUF_PAYLOAD_END) { \
693  LOG_WARN("Not enough packetbuf space to compress header (%u bytes, %u left). Aborting.\n", \
694  (unsigned)(writelen), (unsigned)(PACKETBUF_PAYLOAD_END - hc06_ptr)); \
695  return 0; \
696  } \
697 } while(0);
698 
699  hc06_ptr = PACKETBUF_IPHC_BUF + 2;
700 
701  /* Check if there is enough space for the compressed IPv6 header, in the
702  * worst case (least compressed case). Extension headers and transport
703  * layer will be checked when they are compressed. */
704  CHECK_BUFFER_SPACE(38);
705 
706  /*
707  * As we copy some bit-length fields, in the IPHC encoding bytes,
708  * we sometimes use |=
709  * If the field is 0, and the current bit value in memory is 1,
710  * this does not work. We therefore reset the IPHC encoding here
711  */
712 
713  iphc0 = SICSLOWPAN_DISPATCH_IPHC;
714  iphc1 = 0;
715  PACKETBUF_IPHC_BUF[2] = 0; /* might not be used - but needs to be cleared */
716 
717  /*
718  * Address handling needs to be made first since it might
719  * cause an extra byte with [ SCI | DCI ]
720  *
721  */
722 
723 
724  /* check if dest context exists (for allocating third byte) */
725  /* TODO: fix this so that it remembers the looked up values for
726  avoiding two lookups - or set the lookup values immediately */
727  if(addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr) != NULL ||
728  addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr) != NULL) {
729  /* set context flag and increase hc06_ptr */
730  LOG_DBG("compression: dest or src ipaddr - setting CID\n");
731  iphc1 |= SICSLOWPAN_IPHC_CID;
732  hc06_ptr++;
733  }
734 
735  /*
736  * Traffic class, flow label
737  * If flow label is 0, compress it. If traffic class is 0, compress it
738  * We have to process both in the same time as the offset of traffic class
739  * depends on the presence of version and flow label
740  */
741 
742  /* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
743 
744  tmp = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
745  tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
746 
747  if(((UIP_IP_BUF->tcflow & 0x0F) == 0) &&
748  (UIP_IP_BUF->flow == 0)) {
749  /* flow label can be compressed */
750  iphc0 |= SICSLOWPAN_IPHC_FL_C;
751  if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
752  ((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
753  /* compress (elide) all */
754  iphc0 |= SICSLOWPAN_IPHC_TC_C;
755  } else {
756  /* compress only the flow label */
757  *hc06_ptr = tmp;
758  hc06_ptr += 1;
759  }
760  } else {
761  /* Flow label cannot be compressed */
762  if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
763  ((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
764  /* compress only traffic class */
765  iphc0 |= SICSLOWPAN_IPHC_TC_C;
766  *hc06_ptr = (tmp & 0xc0) |
767  (UIP_IP_BUF->tcflow & 0x0F);
768  memcpy(hc06_ptr + 1, &UIP_IP_BUF->flow, 2);
769  hc06_ptr += 3;
770  } else {
771  /* compress nothing */
772  memcpy(hc06_ptr, &UIP_IP_BUF->vtc, 4);
773  /* but replace the top byte with the new ECN | DSCP format*/
774  *hc06_ptr = tmp;
775  hc06_ptr += 4;
776  }
777  }
778 
779  /* Note that the payload length is always compressed */
780 
781  /* Next header. We compress it is compressable. */
782  if(IS_COMPRESSABLE_PROTO(UIP_IP_BUF->proto)) {
783  iphc0 |= SICSLOWPAN_IPHC_NH_C;
784  }
785 
786  /* Add proto header unless it is compressed */
787  if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
788  *hc06_ptr = UIP_IP_BUF->proto;
789  hc06_ptr += 1;
790  }
791 
792  /*
793  * Hop limit
794  * if 1: compress, encoding is 01
795  * if 64: compress, encoding is 10
796  * if 255: compress, encoding is 11
797  * else do not compress
798  */
799  switch(UIP_IP_BUF->ttl) {
800  case 1:
801  iphc0 |= SICSLOWPAN_IPHC_TTL_1;
802  break;
803  case 64:
804  iphc0 |= SICSLOWPAN_IPHC_TTL_64;
805  break;
806  case 255:
807  iphc0 |= SICSLOWPAN_IPHC_TTL_255;
808  break;
809  default:
810  *hc06_ptr = UIP_IP_BUF->ttl;
811  hc06_ptr += 1;
812  break;
813  }
814 
815  /* source address - cannot be multicast */
816  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
817  LOG_DBG("compression: addr unspecified - setting SAC\n");
818  iphc1 |= SICSLOWPAN_IPHC_SAC;
819  iphc1 |= SICSLOWPAN_IPHC_SAM_00;
820  } else if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr))
821  != NULL) {
822  /* elide the prefix - indicate by CID and set context + SAC */
823  LOG_DBG("compression: src with context - setting CID & SAC ctx: %d\n",
824  context->number);
825  iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
826  PACKETBUF_IPHC_BUF[2] |= context->number << 4;
827  /* compession compare with this nodes address (source) */
828 
829  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
830  &UIP_IP_BUF->srcipaddr, &uip_lladdr);
831  /* No context found for this address */
832  } else if(uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) &&
833  UIP_IP_BUF->destipaddr.u16[1] == 0 &&
834  UIP_IP_BUF->destipaddr.u16[2] == 0 &&
835  UIP_IP_BUF->destipaddr.u16[3] == 0) {
836  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
837  &UIP_IP_BUF->srcipaddr, &uip_lladdr);
838  } else {
839  /* send the full address => SAC = 0, SAM = 00 */
840  iphc1 |= SICSLOWPAN_IPHC_SAM_00; /* 128-bits */
841  memcpy(hc06_ptr, &UIP_IP_BUF->srcipaddr.u16[0], 16);
842  hc06_ptr += 16;
843  }
844 
845  /* dest address*/
846  if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
847  /* Address is multicast, try to compress */
848  iphc1 |= SICSLOWPAN_IPHC_M;
849  if(sicslowpan_is_mcast_addr_compressable8(&UIP_IP_BUF->destipaddr)) {
850  iphc1 |= SICSLOWPAN_IPHC_DAM_11;
851  /* use last byte */
852  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[15];
853  hc06_ptr += 1;
854  } else if(sicslowpan_is_mcast_addr_compressable32(&UIP_IP_BUF->destipaddr)) {
855  iphc1 |= SICSLOWPAN_IPHC_DAM_10;
856  /* second byte + the last three */
857  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
858  memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[13], 3);
859  hc06_ptr += 4;
860  } else if(sicslowpan_is_mcast_addr_compressable48(&UIP_IP_BUF->destipaddr)) {
861  iphc1 |= SICSLOWPAN_IPHC_DAM_01;
862  /* second byte + the last five */
863  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
864  memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[11], 5);
865  hc06_ptr += 6;
866  } else {
867  iphc1 |= SICSLOWPAN_IPHC_DAM_00;
868  /* full address */
869  memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u8[0], 16);
870  hc06_ptr += 16;
871  }
872  } else {
873  /* Address is unicast, try to compress */
874  if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr)) != NULL) {
875  /* elide the prefix */
876  iphc1 |= SICSLOWPAN_IPHC_DAC;
877  PACKETBUF_IPHC_BUF[2] |= context->number;
878  /* compession compare with link adress (destination) */
879 
880  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
881  &UIP_IP_BUF->destipaddr,
882  (uip_lladdr_t *)link_destaddr);
883  /* No context found for this address */
884  } else if(uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) &&
885  UIP_IP_BUF->destipaddr.u16[1] == 0 &&
886  UIP_IP_BUF->destipaddr.u16[2] == 0 &&
887  UIP_IP_BUF->destipaddr.u16[3] == 0) {
888  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
889  &UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
890  } else {
891  /* send the full address */
892  iphc1 |= SICSLOWPAN_IPHC_DAM_00; /* 128-bits */
893  memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u16[0], 16);
894  hc06_ptr += 16;
895  }
896  }
897 
898  uncomp_hdr_len = UIP_IPH_LEN;
899 
900  /* Start of ext hdr compression or UDP compression */
901  /* pick out the next-header position */
902  next_hdr = &UIP_IP_BUF->proto;
903  next_nhc = hc06_ptr; /* here we set the next header is compressed. */
904  ext_hdr_len = 0;
905  /* reserve the write place of this next header position */
906  LOG_DBG("compression: first header: %d\n", *next_hdr);
907  while(next_hdr != NULL && IS_COMPRESSABLE_PROTO(*next_hdr)) {
908  LOG_DBG("compression: next header: %d\n", *next_hdr);
909  int proto = -1; /* used for the specific ext hdr */
910  /* UDP and EXT header compression */
911  switch(*next_hdr) {
912  case UIP_PROTO_HBHO:
913  proto = SICSLOWPAN_NHC_ETX_HDR_HBHO;
914  case UIP_PROTO_ROUTING:
915  proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_ROUTING : proto;
916  case UIP_PROTO_FRAG:
917  proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_FRAG : proto;
918  case UIP_PROTO_DESTO:
919  /* Handle the header here! */
920  {
921  struct uip_ext_hdr *ext_hdr =
922  (struct uip_ext_hdr *) UIP_IPPAYLOAD_BUF(ext_hdr_len);
923  int len;
924  proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_DESTO : proto;
925  /* Len is defined to be in octets from the length byte */
926  len = (ext_hdr->len << 3) + 8;
927  LOG_DBG("compression: next header %d (len:%d)\n", *next_hdr, len);
928  /* pick up the next header */
929  next_hdr = &ext_hdr->next;
930  /* If the next header is not compressable we need to reserve the
931  NHC byte extra - before the next header here. This is due to
932  next not being elided in that case. */
933  if(!IS_COMPRESSABLE_PROTO(*next_hdr)) {
934  CHECK_BUFFER_SPACE(1);
935  hc06_ptr++;
936  LOG_DBG("compression: keeping the next header in this ext hdr: %d\n",
937  ext_hdr->next);
938  }
939  /* copy the ext-hdr into the hc06 buffer */
940  CHECK_BUFFER_SPACE(len);
941  memcpy(hc06_ptr, ext_hdr, len);
942  /* modify the len to octets */
943  ext_hdr = (struct uip_ext_hdr *) hc06_ptr;
944  ext_hdr->len = len - 2; /* Len should be in bytes from len byte*/
945  ext_hdr_len += len;
946  hc06_ptr += len;
947  uncomp_hdr_len += len;
948 
949  /* Write this next header - with its NHC header - including flag
950  to tell if next header is elided in this one also- */
951  *next_nhc = SICSLOWPAN_NHC_EXT_HDR |
952  (IS_COMPRESSABLE_PROTO(*next_hdr) ? SICSLOWPAN_NHC_BIT : 0) |
953  (proto << 1);
954  /* update the position of the next header */
955  next_nhc = hc06_ptr;
956  }
957  break;
958  case UIP_PROTO_UDP:
959  /* allocate a byte for the next header posision as UDP has no next */
960  hc06_ptr++;
961  udp_buf = UIP_UDP_BUF(ext_hdr_len);
962  LOG_DBG("compression: inlined UDP ports on send side: %x, %x\n",
963  UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
964  /* Mask out the last 4 bits can be used as a mask */
965  if(((UIP_HTONS(udp_buf->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
966  ((UIP_HTONS(udp_buf->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
967  /* we can compress 12 bits of both source and dest */
968  *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_11;
969  LOG_DBG("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
970  CHECK_BUFFER_SPACE(1);
971  *hc06_ptr =
972  (uint8_t)((UIP_HTONS(udp_buf->srcport) -
973  SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
974  (uint8_t)((UIP_HTONS(udp_buf->destport) -
975  SICSLOWPAN_UDP_4_BIT_PORT_MIN));
976  hc06_ptr += 1;
977  } else if((UIP_HTONS(udp_buf->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
978  /* we can compress 8 bits of dest, leave source. */
979  *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_01;
980  LOG_DBG("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
981  CHECK_BUFFER_SPACE(3);
982  memcpy(hc06_ptr, &udp_buf->srcport, 2);
983  *(hc06_ptr + 2) =
984  (uint8_t)((UIP_HTONS(udp_buf->destport) -
985  SICSLOWPAN_UDP_8_BIT_PORT_MIN));
986  hc06_ptr += 3;
987  } else if((UIP_HTONS(udp_buf->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
988  /* we can compress 8 bits of src, leave dest. Copy compressed port */
989  *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_10;
990  LOG_DBG("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *next_nhc);
991  CHECK_BUFFER_SPACE(3);
992  *hc06_ptr =
993  (uint8_t)((UIP_HTONS(udp_buf->srcport) -
994  SICSLOWPAN_UDP_8_BIT_PORT_MIN));
995  memcpy(hc06_ptr + 1, &udp_buf->destport, 2);
996  hc06_ptr += 3;
997  } else {
998  /* we cannot compress. Copy uncompressed ports, full checksum */
999  *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_00;
1000  LOG_DBG("IPHC: cannot compress UDP headers\n");
1001  CHECK_BUFFER_SPACE(4);
1002  memcpy(hc06_ptr, &udp_buf->srcport, 4);
1003  hc06_ptr += 4;
1004  }
1005  /* always inline the checksum */
1006  CHECK_BUFFER_SPACE(2);
1007  memcpy(hc06_ptr, &udp_buf->udpchksum, 2);
1008  hc06_ptr += 2;
1009  uncomp_hdr_len += UIP_UDPH_LEN;
1010  /* this is the final header. */
1011  next_hdr = NULL;
1012  break;
1013  default:
1014  LOG_ERR("compression: could not handle compression of header");
1015  }
1016  }
1017  if(next_hdr != NULL) {
1018  /* Last header could not be compressed - we assume that this is then OK!*/
1019  /* as the last EXT_HDR should be "uncompressed" and have the next there */
1020  LOG_DBG("compression: last header could is not compressed: %d\n", *next_hdr);
1021  }
1022  /* before the packetbuf_hdr_len operation */
1023  PACKETBUF_IPHC_BUF[0] = iphc0;
1024  PACKETBUF_IPHC_BUF[1] = iphc1;
1025 
1026  if(LOG_DBG_ENABLED) {
1027  uint16_t ndx;
1028  LOG_DBG("compression: after (%d): ", (int)(hc06_ptr - packetbuf_ptr));
1029  for(ndx = 0; ndx < hc06_ptr - packetbuf_ptr; ndx++) {
1030  uint8_t data = ((uint8_t *) packetbuf_ptr)[ndx];
1031  LOG_DBG_("%02x", data);
1032  }
1033  LOG_DBG_("\n");
1034  }
1035 
1037 
1038  return 1;
1039 }
1040 
1041 /*--------------------------------------------------------------------*/
1042 /**
1043  * \brief Uncompress IPHC (i.e., IPHC and LOWPAN_UDP) headers and put
1044  * them in sicslowpan_buf
1045  *
1046  * This function is called by the input function when the dispatch is
1047  * IPHC.
1048  * We %process the packet in the packetbuf buffer, uncompress the header
1049  * fields, and copy the result in the sicslowpan buffer.
1050  * At the end of the decompression, packetbuf_hdr_len and uncompressed_hdr_len
1051  * are set to the appropriate values
1052  *
1053  * \param buf Pointer to the buffer to uncompress the packet into.
1054  * \param ip_len Equal to 0 if the packet is not a fragment (IP length
1055  * is then inferred from the L2 length), non 0 if the packet is a 1st
1056  * fragment.
1057  */
1058 static void
1059 uncompress_hdr_iphc(uint8_t *buf, uint16_t ip_len)
1060 {
1061  uint8_t tmp, iphc0, iphc1, nhc;
1062  struct uip_ext_hdr *exthdr;
1063  uint8_t* last_nextheader;
1064  uint8_t* ip_payload;
1065  uint8_t ext_hdr_len = 0;
1066 
1067  /* at least two byte will be used for the encoding */
1069 
1070  iphc0 = PACKETBUF_IPHC_BUF[0];
1071  iphc1 = PACKETBUF_IPHC_BUF[1];
1072 
1073  /* another if the CID flag is set */
1074  if(iphc1 & SICSLOWPAN_IPHC_CID) {
1075  LOG_DBG("uncompression: CID flag set - increase header with one\n");
1076  hc06_ptr++;
1077  }
1078 
1079  /* Traffic class and flow label */
1080  if((iphc0 & SICSLOWPAN_IPHC_FL_C) == 0) {
1081  /* Flow label are carried inline */
1082  if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1083  /* Traffic class is carried inline */
1084  memcpy(&SICSLOWPAN_IP_BUF(buf)->tcflow, hc06_ptr + 1, 3);
1085  tmp = *hc06_ptr;
1086  hc06_ptr += 4;
1087  /* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
1088  /* set version, pick highest DSCP bits and set in vtc */
1089  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((tmp >> 2) & 0x0f);
1090  /* ECN rolled down two steps + lowest DSCP bits at top two bits */
1091  SICSLOWPAN_IP_BUF(buf)->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
1092  (SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f);
1093  } else {
1094  /* Traffic class is compressed (set version and no TC)*/
1095  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1096  /* highest flow label bits + ECN bits */
1097  SICSLOWPAN_IP_BUF(buf)->tcflow = (*hc06_ptr & 0x0F) |
1098  ((*hc06_ptr >> 2) & 0x30);
1099  memcpy(&SICSLOWPAN_IP_BUF(buf)->flow, hc06_ptr + 1, 2);
1100  hc06_ptr += 3;
1101  }
1102  } else {
1103  /* Version is always 6! */
1104  /* Version and flow label are compressed */
1105  if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1106  /* Traffic class is inline */
1107  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*hc06_ptr >> 2) & 0x0f);
1108  SICSLOWPAN_IP_BUF(buf)->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30);
1109  SICSLOWPAN_IP_BUF(buf)->flow = 0;
1110  hc06_ptr += 1;
1111  } else {
1112  /* Traffic class is compressed */
1113  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1114  SICSLOWPAN_IP_BUF(buf)->tcflow = 0;
1115  SICSLOWPAN_IP_BUF(buf)->flow = 0;
1116  }
1117  }
1118 
1119  /* Next Header */
1120  if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
1121  /* Next header is carried inline */
1122  SICSLOWPAN_IP_BUF(buf)->proto = *hc06_ptr;
1123  LOG_DBG("uncompression: next header inline: %d\n", SICSLOWPAN_IP_BUF(buf)->proto);
1124  hc06_ptr += 1;
1125  }
1126 
1127  /* Hop limit */
1128  if((iphc0 & 0x03) != SICSLOWPAN_IPHC_TTL_I) {
1129  SICSLOWPAN_IP_BUF(buf)->ttl = ttl_values[iphc0 & 0x03];
1130  } else {
1131  SICSLOWPAN_IP_BUF(buf)->ttl = *hc06_ptr;
1132  hc06_ptr += 1;
1133  }
1134 
1135  /* put the source address compression mode SAM in the tmp var */
1136  tmp = ((iphc1 & SICSLOWPAN_IPHC_SAM_11) >> SICSLOWPAN_IPHC_SAM_BIT) & 0x03;
1137 
1138  /* context based compression */
1139  if(iphc1 & SICSLOWPAN_IPHC_SAC) {
1140  uint8_t sci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
1141  PACKETBUF_IPHC_BUF[2] >> 4 : 0;
1142 
1143  /* Source address - check context != NULL only if SAM bits are != 0*/
1144  if (tmp != 0) {
1145  context = addr_context_lookup_by_number(sci);
1146  if(context == NULL) {
1147  LOG_ERR("uncompression: error context not found\n");
1148  return;
1149  }
1150  }
1151  /* if tmp == 0 we do not have a context and therefore no prefix */
1152  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr,
1153  tmp != 0 ? context->prefix : NULL, unc_ctxconf[tmp],
1154  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1155  } else {
1156  /* no compression and link local */
1157  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr, llprefix, unc_llconf[tmp],
1158  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1159  }
1160 
1161  /* Destination address */
1162  /* put the destination address compression mode into tmp */
1163  tmp = ((iphc1 & SICSLOWPAN_IPHC_DAM_11) >> SICSLOWPAN_IPHC_DAM_BIT) & 0x03;
1164 
1165  /* multicast compression */
1166  if(iphc1 & SICSLOWPAN_IPHC_M) {
1167  /* context based multicast compression */
1168  if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1169  /* TODO: implement this */
1170  } else {
1171  /* non-context based multicast compression - */
1172  /* DAM_00: 128 bits */
1173  /* DAM_01: 48 bits FFXX::00XX:XXXX:XXXX */
1174  /* DAM_10: 32 bits FFXX::00XX:XXXX */
1175  /* DAM_11: 8 bits FF02::00XX */
1176  uint8_t prefix[] = {0xff, 0x02};
1177  if(tmp > 0 && tmp < 3) {
1178  prefix[1] = *hc06_ptr;
1179  hc06_ptr++;
1180  }
1181 
1182  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, prefix,
1183  unc_mxconf[tmp], NULL);
1184  }
1185  } else {
1186  /* no multicast */
1187  /* Context based */
1188  if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1189  uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
1190  context = addr_context_lookup_by_number(dci);
1191 
1192  /* all valid cases below need the context! */
1193  if(context == NULL) {
1194  LOG_ERR("uncompression: error context not found\n");
1195  return;
1196  }
1197  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, context->prefix,
1198  unc_ctxconf[tmp],
1199  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1200  } else {
1201  /* not context based => link local M = 0, DAC = 0 - same as SAC */
1202  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, llprefix,
1203  unc_llconf[tmp],
1204  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1205  }
1206  }
1207  uncomp_hdr_len += UIP_IPH_LEN;
1208 
1209  /* Next header processing - continued */
1210  nhc = iphc0 & SICSLOWPAN_IPHC_NH_C;
1211  /* The next header is compressed, NHC is following */
1212  last_nextheader = &SICSLOWPAN_IP_BUF(buf)->proto;
1213  ip_payload = SICSLOWPAN_IPPAYLOAD_BUF(buf);
1214 
1215  while(nhc && (*hc06_ptr & SICSLOWPAN_NHC_MASK) == SICSLOWPAN_NHC_EXT_HDR) {
1216  uint8_t eid = (*hc06_ptr & 0x0e) >> 1;
1217  /* next header compression flag */
1218  uint8_t nh = (*hc06_ptr & 0x01);
1219  uint8_t next = 0;
1220  uint8_t len;
1221  uint8_t proto;
1222 
1223  nhc = nh;
1224 
1225  hc06_ptr++;
1226  if(!nh) {
1227  next = *hc06_ptr;
1228  hc06_ptr++;
1229  LOG_DBG("uncompression: next header is inlined. Next: %d\n", next);
1230  }
1231  len = *hc06_ptr;
1232  hc06_ptr++;
1233 
1234  LOG_DBG("uncompression: found ext header id: %d next: %d len: %d\n", eid, next, len);
1235  switch(eid) {
1236  case SICSLOWPAN_NHC_ETX_HDR_HBHO:
1237  proto = UIP_PROTO_HBHO;
1238  break;
1239  case SICSLOWPAN_NHC_ETX_HDR_ROUTING:
1240  proto = UIP_PROTO_ROUTING;
1241  break;
1242  case SICSLOWPAN_NHC_ETX_HDR_FRAG:
1243  proto = UIP_PROTO_FRAG;
1244  break;
1245  case SICSLOWPAN_NHC_ETX_HDR_DESTO:
1246  proto = UIP_PROTO_DESTO;
1247  break;
1248  default:
1249  LOG_DBG("uncompression: error unsupported ext header\n");
1250  return;
1251  }
1252  *last_nextheader = proto;
1253  /* uncompress the extension header */
1254  exthdr = (struct uip_ext_hdr *)ip_payload;
1255  exthdr->len = (2 + len) / 8 - 1;
1256  exthdr->next = next;
1257  last_nextheader = &exthdr->next;
1258  memcpy((uint8_t*)exthdr + 2, hc06_ptr, len);
1259  hc06_ptr += len;
1260  uncomp_hdr_len += (exthdr->len + 1) * 8;
1261  ip_payload += (exthdr->len + 1) * 8;
1262  ext_hdr_len += (exthdr->len + 1) * 8;
1263 
1264  LOG_DBG("uncompression: %d len: %d exhdrlen: %d (calc: %d)\n",
1265  proto, len, exthdr->len, (exthdr->len + 1) * 8);
1266  }
1267 
1268  /* The next header is compressed, NHC is following */
1269  if(nhc && (*hc06_ptr & SICSLOWPAN_NHC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) {
1270  struct uip_udp_hdr *udp_buf = (struct uip_udp_hdr *)ip_payload;
1271  uint16_t udp_len;
1272  uint8_t checksum_compressed;
1273  *last_nextheader = UIP_PROTO_UDP;
1274  checksum_compressed = *hc06_ptr & SICSLOWPAN_NHC_UDP_CHECKSUMC;
1275  LOG_DBG("uncompression: incoming header value: %i\n", *hc06_ptr);
1276  switch(*hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
1277  case SICSLOWPAN_NHC_UDP_CS_P_00:
1278  /* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
1279  memcpy(&udp_buf->srcport, hc06_ptr + 1, 2);
1280  memcpy(&udp_buf->destport, hc06_ptr + 3, 2);
1281  LOG_DBG("uncompression: UDP ports (ptr+5): %x, %x\n",
1282  UIP_HTONS(udp_buf->srcport),
1283  UIP_HTONS(udp_buf->destport));
1284  hc06_ptr += 5;
1285  break;
1286 
1287  case SICSLOWPAN_NHC_UDP_CS_P_01:
1288  /* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
1289  LOG_DBG("uncompression: destination address\n");
1290  memcpy(&udp_buf->srcport, hc06_ptr + 1, 2);
1291  udp_buf->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
1292  LOG_DBG("uncompression: UDP ports (ptr+4): %x, %x\n",
1293  UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1294  hc06_ptr += 4;
1295  break;
1296 
1297  case SICSLOWPAN_NHC_UDP_CS_P_10:
1298  /* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit inline*/
1299  LOG_DBG("uncompression: source address\n");
1300  udp_buf->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
1301  (*(hc06_ptr + 1)));
1302  memcpy(&udp_buf->destport, hc06_ptr + 2, 2);
1303  LOG_DBG("uncompression: UDP ports (ptr+4): %x, %x\n",
1304  UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1305  hc06_ptr += 4;
1306  break;
1307 
1308  case SICSLOWPAN_NHC_UDP_CS_P_11:
1309  /* 1 byte for NHC, 1 byte for ports */
1310  udp_buf->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1311  (*(hc06_ptr + 1) >> 4));
1312  udp_buf->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1313  ((*(hc06_ptr + 1)) & 0x0F));
1314  LOG_DBG("uncompression: UDP ports (ptr+2): %x, %x\n",
1315  UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1316  hc06_ptr += 2;
1317  break;
1318  default:
1319  LOG_DBG("uncompression: error unsupported UDP compression\n");
1320  return;
1321  }
1322  if(!checksum_compressed) { /* has_checksum, default */
1323  memcpy(&udp_buf->udpchksum, hc06_ptr, 2);
1324  hc06_ptr += 2;
1325  LOG_DBG("uncompression: checksum included\n");
1326  } else {
1327  LOG_DBG("uncompression: checksum *NOT* included\n");
1328  }
1329 
1330  /* length field in UDP header (8 byte header + payload) */
1331  udp_len = 8 + packetbuf_datalen() - (hc06_ptr - packetbuf_ptr);
1332  udp_buf->udplen = UIP_HTONS(ip_len == 0 ? udp_len :
1333  ip_len - UIP_IPH_LEN - ext_hdr_len);
1334  LOG_DBG("uncompression: UDP length: %u (ext: %u) ip_len: %d udp_len: %d\n",
1335  UIP_HTONS(udp_buf->udplen), ext_hdr_len, ip_len, udp_len);
1336 
1337  uncomp_hdr_len += UIP_UDPH_LEN;
1338  }
1339 
1340  packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
1341 
1342  /* IP length field. */
1343  if(ip_len == 0) {
1344  int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
1345  LOG_DBG("uncompression: IP payload length: %d. %u - %u + %u - %u\n", len,
1346  packetbuf_datalen(), packetbuf_hdr_len, uncomp_hdr_len, UIP_IPH_LEN);
1347 
1348  /* This is not a fragmented packet */
1349  SICSLOWPAN_IP_BUF(buf)->len[0] = len >> 8;
1350  SICSLOWPAN_IP_BUF(buf)->len[1] = len & 0x00FF;
1351  } else {
1352  /* This is a 1st fragment */
1353  SICSLOWPAN_IP_BUF(buf)->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
1354  SICSLOWPAN_IP_BUF(buf)->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
1355  }
1356 }
1357 /** @} */
1358 #endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
1359 
1360 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH
1361 /*--------------------------------------------------------------------*/
1362 /**
1363  * \brief Adds Paging dispatch byte
1364  */
1365 static void
1366 add_paging_dispatch(uint8_t page)
1367 {
1368  /* Add paging dispatch to Page 1 */
1369  PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] = SICSLOWPAN_DISPATCH_PAGING | (page & 0x0f);
1371 }
1372 /*--------------------------------------------------------------------*/
1373 /**
1374  * \brief Adds 6lorh headers before IPHC
1375  */
1376 static void
1378 {
1379  /* 6LoRH is not implemented yet */
1380 }
1381 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */
1382 
1383 /*--------------------------------------------------------------------*/
1384 /**
1385  * \brief Digest 6lorh headers before IPHC
1386  */
1387 static void
1389 {
1390  /* Is this a paging dispatch? */
1391  if((PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_PAGING_MASK) == SICSLOWPAN_DISPATCH_PAGING) {
1392  /* Parse page number */
1393  curr_page = PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & 0x0f;
1395  }
1396 }
1397 /*--------------------------------------------------------------------*/
1398 /**
1399  * \brief Digest 6lorh headers before IPHC
1400  */
1401 static void
1403 {
1404  /* 6LoRH is not implemented yet */
1405 }
1406 /*--------------------------------------------------------------------*/
1407 /** \name IPv6 dispatch "compression" function
1408  * @{ */
1409 /*--------------------------------------------------------------------*/
1410 /* \brief Packets "Compression" when only IPv6 dispatch is used
1411  *
1412  * There is no compression in this case, all fields are sent
1413  * inline. We just add the IPv6 dispatch byte before the packet.
1414  * \verbatim
1415  * 0 1 2 3
1416  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1417  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1418  * | IPv6 Dsp | IPv6 header and payload ...
1419  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1420  * \endverbatim
1421  */
1422  #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
1423 static void
1424 compress_hdr_ipv6(linkaddr_t *link_destaddr)
1425 {
1426  *packetbuf_ptr = SICSLOWPAN_DISPATCH_IPV6;
1427  packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
1428  memcpy(packetbuf_ptr + packetbuf_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
1429  packetbuf_hdr_len += UIP_IPH_LEN;
1430  uncomp_hdr_len += UIP_IPH_LEN;
1431  return;
1432 }
1433 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
1434 /** @} */
1435 
1436 /*--------------------------------------------------------------------*/
1437 /** \name Input/output functions common to all compression schemes
1438  * @{ */
1439 /*--------------------------------------------------------------------*/
1440 /**
1441  * Callback function for the MAC packet sent callback
1442  */
1443 static void
1444 packet_sent(void *ptr, int status, int transmissions)
1445 {
1446  const linkaddr_t *dest;
1447 
1448  if(callback != NULL) {
1449  callback->output_callback(status);
1450  }
1451  last_tx_status = status;
1452 
1453  /* What follows only applies to unicast */
1454  dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
1455  if(linkaddr_cmp(dest, &linkaddr_null)) {
1456  return;
1457  }
1458 
1459  /* Update neighbor link statistics */
1460  link_stats_packet_sent(dest, status, transmissions);
1461 
1462  /* Call routing protocol link callback */
1463  NETSTACK_ROUTING.link_callback(dest, status, transmissions);
1464 
1465  /* DS6 callback, used for UIP_DS6_LL_NUD */
1466  uip_ds6_link_callback(status, transmissions);
1467 }
1468 /*--------------------------------------------------------------------*/
1469 /**
1470  * \brief This function is called by the 6lowpan code to send out a
1471  * packet.
1472  * \param dest the link layer destination address of the packet
1473  */
1474 static void
1475 send_packet(linkaddr_t *dest)
1476 {
1477  /* Set the link layer destination address for the packet as a
1478  * packetbuf attribute. The MAC layer can access the destination
1479  * address with the function packetbuf_addr(PACKETBUF_ADDR_RECEIVER).
1480  */
1481  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest);
1482 
1483 #if NETSTACK_CONF_BRIDGE_MODE
1484  /* This needs to be explicitly set here for bridge mode to work */
1485  packetbuf_set_addr(PACKETBUF_ADDR_SENDER,(void*)&uip_lladdr);
1486 #endif
1487 
1488  /* Provide a callback function to receive the result of
1489  a packet transmission. */
1490  NETSTACK_MAC.send(&packet_sent, NULL);
1491 
1492  /* If we are sending multiple packets in a row, we need to let the
1493  watchdog know that we are still alive. */
1495 }
1496 #if SICSLOWPAN_CONF_FRAG
1497 /*--------------------------------------------------------------------*/
1498 /**
1499  * \brief This function is called by the 6lowpan code to copy a fragment's
1500  * payload from uIP and send it down the stack.
1501  * \param uip_offset the offset in the uIP buffer where to copy the payload from
1502  * \param dest the link layer destination address of the packet
1503  * \return 1 if success, 0 otherwise
1504  */
1505 static int
1506 fragment_copy_payload_and_send(uint16_t uip_offset, linkaddr_t *dest) {
1507  struct queuebuf *q;
1508 
1509  /* Now copy fragment payload from uip_buf */
1511  (uint8_t *)UIP_IP_BUF + uip_offset, packetbuf_payload_len);
1513 
1514  /* Backup packetbuf to queuebuf. Enables preserving attributes for all framgnets */
1515  q = queuebuf_new_from_packetbuf();
1516  if(q == NULL) {
1517  LOG_WARN("output: could not allocate queuebuf, dropping fragment\n");
1518  return 0;
1519  }
1520 
1521  /* Send fragment */
1522  send_packet(dest);
1523 
1524  /* Restore packetbuf from queuebuf */
1525  queuebuf_to_packetbuf(q);
1526  queuebuf_free(q);
1527 
1528  /* Check tx result. */
1529  if((last_tx_status == MAC_TX_COLLISION) ||
1530  (last_tx_status == MAC_TX_ERR) ||
1531  (last_tx_status == MAC_TX_ERR_FATAL)) {
1532  LOG_ERR("output: error in fragment tx, dropping subsequent fragments.\n");
1533  return 0;
1534  }
1535  return 1;
1536 }
1537 #endif /* SICSLOWPAN_CONF_FRAG */
1538 /*--------------------------------------------------------------------*/
1539 /** \brief Take an IP packet and format it to be sent on an 802.15.4
1540  * network using 6lowpan.
1541  * \param localdest The MAC address of the destination
1542  *
1543  * The IP packet is initially in uip_buf. Its header is compressed
1544  * and if necessary it is fragmented. The resulting
1545  * packet/fragments are put in packetbuf and delivered to the 802.15.4
1546  * MAC.
1547  */
1548 static uint8_t
1549 output(const linkaddr_t *localdest)
1550 {
1551  int framer_hdrlen;
1552  int max_payload;
1553  int frag_needed;
1554 
1555  /* The MAC address of the destination of the packet */
1556  linkaddr_t dest;
1557 
1558  /* init */
1559  uncomp_hdr_len = 0;
1560  packetbuf_hdr_len = 0;
1561 
1562  /* reset packetbuf buffer */
1563  packetbuf_clear();
1565 
1566  if(callback) {
1567  /* call the attribution when the callback comes, but set attributes
1568  here ! */
1569  set_packet_attrs();
1570  }
1571 
1572  /*
1573  * The destination address will be tagged to each outbound
1574  * packet. If the argument localdest is NULL, we are sending a
1575  * broadcast packet.
1576  */
1577  if(localdest == NULL) {
1578  linkaddr_copy(&dest, &linkaddr_null);
1579  } else {
1580  linkaddr_copy(&dest, localdest);
1581  }
1582 
1583  LOG_INFO("output: sending IPv6 packet with len %d\n", uip_len);
1584 
1585  /* copy over the retransmission count from uipbuf attributes */
1586  packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
1587  uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
1588 
1589 /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC */
1590  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1591  framer_hdrlen = NETSTACK_FRAMER.length();
1592  if(framer_hdrlen < 0) {
1593  /* Framing failed, we assume the maximum header length */
1594  framer_hdrlen = MAC_MAX_HEADER;
1595  }
1596 
1597  mac_max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
1598 
1599  /* Try to compress the headers */
1600 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
1601  compress_hdr_ipv6(&dest);
1602 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
1603 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH
1604  /* Add 6LoRH headers before IPHC. Only needed on routed traffic
1605  (non link-local). */
1606  if(!uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr)) {
1608  add_6lorh_hdr();
1609  }
1610 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */
1611 #if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC
1612  if(compress_hdr_iphc(&dest) == 0) {
1613  /* Warning should already be issued by function above */
1614  return 0;
1615  }
1616 #endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
1617 
1618  /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC.
1619  * We calculate it here only to make a better decision of whether the outgoing packet
1620  * needs to be fragmented or not. */
1621  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1622  framer_hdrlen = NETSTACK_FRAMER.length();
1623  if(framer_hdrlen < 0) {
1624  /* Framing failed, we assume the maximum header length */
1625  framer_hdrlen = MAC_MAX_HEADER;
1626  }
1627 
1628  max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
1629  frag_needed = (int)uip_len - (int)uncomp_hdr_len + (int)packetbuf_hdr_len > max_payload;
1630  LOG_INFO("output: header len %d -> %d, total len %d -> %d, MAC max payload %d, frag_needed %d\n",
1633  max_payload, frag_needed);
1634 
1635  if(frag_needed) {
1636 #if SICSLOWPAN_CONF_FRAG
1637  /* Number of bytes processed. */
1638  uint16_t processed_ip_out_len;
1639  uint16_t frag_tag;
1640  int curr_frag = 0;
1641 
1642  /*
1643  * The outbound IPv6 packet is too large to fit into a single 15.4
1644  * packet, so we fragment it into multiple packets and send them.
1645  * The first fragment contains frag1 dispatch, then IPv6/IPHC/HC_UDP
1646  * dispatchs/headers and IPv6 payload (with len multiple of 8 bytes).
1647  * The subsequent fragments contain the FRAGN dispatch and more of the
1648  * IPv6 payload (still multiple of 8 bytes, except for the last fragment)
1649  */
1650  /* Total IPv6 payload */
1651  int total_payload = (uip_len - uncomp_hdr_len);
1652  /* IPv6 payload that goes to first fragment */
1653  int frag1_payload = (max_payload - packetbuf_hdr_len - SICSLOWPAN_FRAG1_HDR_LEN) & 0xfffffff8;
1654  /* max IPv6 payload in each FRAGN. Must be multiple of 8 bytes */
1655  int fragn_max_payload = (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) & 0xfffffff8;
1656  /* max IPv6 payload in the last fragment. Needs not be multiple of 8 bytes */
1657  int last_fragn_max_payload = max_payload - SICSLOWPAN_FRAGN_HDR_LEN;
1658  /* sum of all IPv6 payload that goes to non-first and non-last fragments */
1659  int middle_fragn_total_payload = MAX(total_payload - frag1_payload - last_fragn_max_payload, 0);
1660  /* Ceiling of: 2 + middle_fragn_total_payload / fragn_max_payload */
1661  int fragment_count = 2;
1662  if(middle_fragn_total_payload > 0) {
1663  fragment_count += 1 + (middle_fragn_total_payload - 1) / fragn_max_payload;
1664  }
1665 
1666  int freebuf = queuebuf_numfree() - 1;
1667  LOG_INFO("output: fragmentation needed, fragments: %u, free queuebufs: %u\n",
1668  fragment_count, freebuf);
1669 
1670  if(freebuf < fragment_count) {
1671  LOG_WARN("output: dropping packet, not enough free bufs (needed: %u, free: %u)\n",
1672  fragment_count, freebuf);
1673  return 0;
1674  }
1675 
1676  if(frag1_payload < 0) {
1677  /* The current implementation requires that all headers fit in the first
1678  * fragment. Here is a corner case where the header did fit packetbuf
1679  * but do no longer fit after truncating for a length multiple of 8. */
1680  LOG_WARN("output: compressed header does not fit first fragment\n");
1681  return 0;
1682  }
1683 
1684  /* Reset last tx status -- MAC layers most often call packet_sent asynchrously */
1686  /* Update fragment tag */
1687  frag_tag = my_tag++;
1688 
1689  /* Move IPHC/IPv6 header to make room for FRAG1 header */
1690  memmove(packetbuf_ptr + SICSLOWPAN_FRAG1_HDR_LEN, packetbuf_ptr, packetbuf_hdr_len);
1691  packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
1692 
1693  /* Set FRAG1 header */
1694  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1695  ((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len));
1696  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG, frag_tag);
1697 
1698  /* Set frag1 payload len. Was already caulcated earlier as frag1_payload */
1699  packetbuf_payload_len = frag1_payload;
1700 
1701  /* Copy payload from uIP and send fragment */
1702  /* Send fragment */
1703  LOG_INFO("output: fragment %d/%d (tag %d, payload %d)\n",
1704  curr_frag + 1, fragment_count,
1705  frag_tag, packetbuf_payload_len);
1706  if(fragment_copy_payload_and_send(uncomp_hdr_len, &dest) == 0) {
1707  return 0;
1708  }
1709 
1710  /* Now prepare for subsequent fragments. */
1711 
1712  /* FRAGN header: tag was already set at FRAG1. Now set dispatch for all FRAGN */
1713  packetbuf_hdr_len = SICSLOWPAN_FRAGN_HDR_LEN;
1714  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1715  ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
1716 
1717  /* Keep track of the total length of data sent */
1718  processed_ip_out_len = uncomp_hdr_len + packetbuf_payload_len;
1719 
1720  /* Create and send subsequent fragments. */
1721  while(processed_ip_out_len < uip_len) {
1722  curr_frag++;
1723  /* FRAGN header: set offset for this fragment */
1724  PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
1725 
1726  /* Calculate fragment len */
1727  if(uip_len - processed_ip_out_len > last_fragn_max_payload) {
1728  /* Not last fragment, send max FRAGN payload */
1729  packetbuf_payload_len = fragn_max_payload;
1730  } else {
1731  /* last fragment */
1732  packetbuf_payload_len = uip_len - processed_ip_out_len;
1733  }
1734 
1735  /* Copy payload from uIP and send fragment */
1736  /* Send fragment */
1737  LOG_INFO("output: fragment %d/%d (tag %d, payload %d, offset %d)\n",
1738  curr_frag + 1, fragment_count,
1739  frag_tag, packetbuf_payload_len, processed_ip_out_len);
1740  if(fragment_copy_payload_and_send(processed_ip_out_len, &dest) == 0) {
1741  return 0;
1742  }
1743 
1744  processed_ip_out_len += packetbuf_payload_len;
1745  }
1746 #else /* SICSLOWPAN_CONF_FRAG */
1747  LOG_ERR("output: Packet too large to be sent without fragmentation support; dropping packet\n");
1748  return 0;
1749 #endif /* SICSLOWPAN_CONF_FRAG */
1750  } else {
1751 
1752  /*
1753  * The packet does not need to be fragmented
1754  * copy "payload" and send
1755  */
1759  send_packet(&dest);
1760  }
1761  return 1;
1762 }
1763 
1764 /*--------------------------------------------------------------------*/
1765 /** \brief Process a received 6lowpan packet.
1766  *
1767  * The 6lowpan packet is put in packetbuf by the MAC. If its a frag1 or
1768  * a non-fragmented packet we first uncompress the IP header. The
1769  * 6lowpan payload and possibly the uncompressed IP header are then
1770  * copied in siclowpan_buf. If the IP packet is complete it is copied
1771  * to uip_buf and the IP layer is called.
1772  *
1773  * \note We do not check for overlapping sicslowpan fragments
1774  * (it is a SHALL in the RFC 4944 and should never happen)
1775  */
1776 static void
1777 input(void)
1778 {
1779  /* size of the IP packet (read from fragment) */
1780  uint16_t frag_size = 0;
1781  /* offset of the fragment in the IP packet */
1782  uint8_t frag_offset = 0;
1783  uint8_t *buffer;
1784 
1785 #if SICSLOWPAN_CONF_FRAG
1786  uint8_t is_fragment = 0;
1787  int8_t frag_context = 0;
1788 
1789  /* tag of the fragment */
1790  uint16_t frag_tag = 0;
1791  uint8_t first_fragment = 0, last_fragment = 0;
1792 #endif /*SICSLOWPAN_CONF_FRAG*/
1793 
1794  /* Update link statistics */
1795  link_stats_input_callback(packetbuf_addr(PACKETBUF_ADDR_SENDER));
1796 
1797  /* init */
1798  uncomp_hdr_len = 0;
1799  packetbuf_hdr_len = 0;
1800 
1801  /* The MAC puts the 15.4 payload inside the packetbuf data buffer */
1803 
1804  if(packetbuf_datalen() == 0) {
1805  LOG_WARN("input: empty packet\n");
1806  return;
1807  }
1808 
1809  /* This is default uip_buf since we assume that this is not fragmented */
1810  buffer = (uint8_t *)UIP_IP_BUF;
1811 
1812  /* Save the RSSI of the incoming packet in case the upper layer will
1813  want to query us for it later. */
1814  last_rssi = (signed short)packetbuf_attr(PACKETBUF_ATTR_RSSI);
1815 
1816 #if SICSLOWPAN_CONF_FRAG
1817 
1818  /*
1819  * Since we don't support the mesh and broadcast header, the first header
1820  * we look for is the fragmentation header
1821  */
1822  switch((GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) >> 8) & SICSLOWPAN_DISPATCH_FRAG_MASK) {
1823  case SICSLOWPAN_DISPATCH_FRAG1:
1824  frag_offset = 0;
1825  frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1826  frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1827  packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
1828  first_fragment = 1;
1829  is_fragment = 1;
1830 
1831  LOG_INFO("input: received first element of a fragmented packet (tag %d, len %d)\n",
1832  frag_tag, frag_size);
1833 
1834  /* Add the fragment to the fragmentation context */
1835  frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1836 
1837  if(frag_context == -1) {
1838  LOG_ERR("input: failed to allocate new reassembly context\n");
1839  return;
1840  }
1841 
1842  buffer = frag_info[frag_context].first_frag;
1843 
1844  break;
1845  case SICSLOWPAN_DISPATCH_FRAGN:
1846  /*
1847  * set offset, tag, size
1848  * Offset is in units of 8 bytes
1849  */
1850  frag_offset = PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET];
1851  frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1852  frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1853  packetbuf_hdr_len += SICSLOWPAN_FRAGN_HDR_LEN;
1854 
1855  /* Add the fragment to the fragmentation context (this will also
1856  copy the payload) */
1857  frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1858 
1859  if(frag_context == -1) {
1860  LOG_ERR("input: reassembly context not found (tag %d)\n", frag_tag);
1861  return;
1862  }
1863 
1864  /* Ok - add_fragment will store the fragment automatically - so
1865  we should not store more */
1866  buffer = NULL;
1867 
1868  if(frag_info[frag_context].reassembled_len >= frag_size) {
1869  last_fragment = 1;
1870  }
1871  is_fragment = 1;
1872  break;
1873  default:
1874  break;
1875  }
1876 
1877  if(is_fragment && !first_fragment) {
1878  /* this is a FRAGN, skip the header compression dispatch section */
1879  goto copypayload;
1880  }
1881 #endif /* SICSLOWPAN_CONF_FRAG */
1882 
1883  /* First, process 6LoRH headers */
1884  curr_page = 0;
1886  if(curr_page == 1) {
1887  LOG_INFO("input: page 1, 6LoRH\n");
1888  digest_6lorh_hdr();
1889  } else if (curr_page > 1) {
1890  LOG_ERR("input: page %u not supported\n", curr_page);
1891  return;
1892  }
1893 
1894  /* Process next dispatch and headers */
1895  if((PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK) == SICSLOWPAN_DISPATCH_IPHC) {
1896  LOG_DBG("uncompression: IPHC dispatch\n");
1897  uncompress_hdr_iphc(buffer, frag_size);
1898  } else if(PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] == SICSLOWPAN_DISPATCH_IPV6) {
1899  LOG_DBG("uncompression: IPV6 dispatch\n");
1900  packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
1901 
1902  /* Put uncompressed IP header in sicslowpan_buf. */
1903  memcpy(buffer, packetbuf_ptr + packetbuf_hdr_len, UIP_IPH_LEN);
1904 
1905  /* Update uncomp_hdr_len and packetbuf_hdr_len. */
1906  packetbuf_hdr_len += UIP_IPH_LEN;
1907  uncomp_hdr_len += UIP_IPH_LEN;
1908  } else {
1909  LOG_ERR("uncompression: unknown dispatch: 0x%02x\n",
1910  PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK);
1911  return;
1912  }
1913 
1914 #if SICSLOWPAN_CONF_FRAG
1915  copypayload:
1916 #endif /*SICSLOWPAN_CONF_FRAG*/
1917  /*
1918  * copy "payload" from the packetbuf buffer to the sicslowpan_buf
1919  * if this is a first fragment or not fragmented packet,
1920  * we have already copied the compressed headers, uncomp_hdr_len
1921  * and packetbuf_hdr_len are non 0, frag_offset is.
1922  * If this is a subsequent fragment, this is the contrary.
1923  */
1925  LOG_ERR("input: packet dropped due to header > total packet\n");
1926  return;
1927  }
1929 
1930 #if SICSLOWPAN_CONF_FRAG
1931  if(is_fragment) {
1932  LOG_INFO("input: fragment (tag %d, payload %d, offset %d) -- %u %u\n",
1933  frag_tag, packetbuf_payload_len, frag_offset << 3, packetbuf_datalen(), packetbuf_hdr_len);
1934  }
1935 #endif /*SICSLOWPAN_CONF_FRAG*/
1936 
1937  /* Sanity-check size of incoming packet to avoid buffer overflow */
1938  {
1939  int req_size = UIP_LLH_LEN + uncomp_hdr_len + (uint16_t)(frag_offset << 3)
1941  if(req_size > sizeof(uip_buf)) {
1942  LOG_ERR(
1943  "input: packet dropped, minimum required IP_BUF size: %d+%d+%d+%d=%d (current size: %u)\n",
1944  UIP_LLH_LEN, uncomp_hdr_len, (uint16_t)(frag_offset << 3),
1945  packetbuf_payload_len, req_size, (unsigned)sizeof(uip_buf));
1946  return;
1947  }
1948  }
1949 
1950  /* copy the payload if buffer is non-null - which is only the case with first fragment
1951  or packets that are non fragmented */
1952  if(buffer != NULL) {
1953  memcpy((uint8_t *)buffer + uncomp_hdr_len, packetbuf_ptr + packetbuf_hdr_len, packetbuf_payload_len);
1954  }
1955 
1956  /* update processed_ip_in_len if fragment, sicslowpan_len otherwise */
1957 
1958 #if SICSLOWPAN_CONF_FRAG
1959  if(frag_size > 0) {
1960  /* Add the size of the header only for the first fragment. */
1961  if(first_fragment != 0) {
1962  frag_info[frag_context].reassembled_len = uncomp_hdr_len + packetbuf_payload_len;
1963  frag_info[frag_context].first_frag_len = uncomp_hdr_len + packetbuf_payload_len;
1964  }
1965  /* For the last fragment, we are OK if there is extrenous bytes at
1966  the end of the packet. */
1967  if(last_fragment != 0) {
1968  frag_info[frag_context].reassembled_len = frag_size;
1969  /* copy to uip */
1970  copy_frags2uip(frag_context);
1971  }
1972  }
1973 
1974  /*
1975  * If we have a full IP packet in sicslowpan_buf, deliver it to
1976  * the IP stack
1977  */
1978  if(!is_fragment || last_fragment) {
1979  /* packet is in uip already - just set length */
1980  if(is_fragment != 0 && last_fragment != 0) {
1981  uip_len = frag_size;
1982  } else {
1984  }
1985 #else
1987 #endif /* SICSLOWPAN_CONF_FRAG */
1988  LOG_INFO("input: received IPv6 packet with len %d\n",
1989  uip_len);
1990 
1991  if(LOG_DBG_ENABLED) {
1992  uint16_t ndx;
1993  LOG_DBG("uncompression: after (%u):", UIP_IP_BUF->len[1]);
1994  for (ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
1995  uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
1996  LOG_DBG_("%02x", data);
1997  }
1998  LOG_DBG_("\n");
1999  }
2000 
2001  /* if callback is set then set attributes and call */
2002  if(callback) {
2003  set_packet_attrs();
2004  callback->input_callback();
2005  }
2006 
2007  tcpip_input();
2008 #if SICSLOWPAN_CONF_FRAG
2009  }
2010 #endif /* SICSLOWPAN_CONF_FRAG */
2011 }
2012 /** @} */
2013 
2014 /*--------------------------------------------------------------------*/
2015 /* \brief 6lowpan init function (called by the MAC layer) */
2016 /*--------------------------------------------------------------------*/
2017 void
2018 sicslowpan_init(void)
2019 {
2020 
2021 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC
2022 /* Preinitialize any address contexts for better header compression
2023  * (Saves up to 13 bytes per 6lowpan packet)
2024  * The platform contiki-conf.h file can override this using e.g.
2025  * #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xbb;addr_contexts[0].prefix[1]=0xbb;}
2026  */
2027 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
2028  addr_contexts[0].used = 1;
2029  addr_contexts[0].number = 0;
2030 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0
2031  SICSLOWPAN_CONF_ADDR_CONTEXT_0;
2032 #else
2033  addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0;
2034  addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1;
2035 #endif
2036 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
2037 
2038 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1
2039  {
2040  int i;
2041  for(i = 1; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
2042 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1
2043  if (i==1) {
2044  addr_contexts[1].used = 1;
2045  addr_contexts[1].number = 1;
2046  SICSLOWPAN_CONF_ADDR_CONTEXT_1;
2047 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
2048  } else if (i==2) {
2049  addr_contexts[2].used = 1;
2050  addr_contexts[2].number = 2;
2051  SICSLOWPAN_CONF_ADDR_CONTEXT_2;
2052 #endif
2053  } else {
2054  addr_contexts[i].used = 0;
2055  }
2056 #else
2057  addr_contexts[i].used = 0;
2058 #endif /* SICSLOWPAN_CONF_ADDR_CONTEXT_1 */
2059  }
2060  }
2061 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */
2062 
2063 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC */
2064 
2065  /* We use the queuebuf module if fragmentation is enabled */
2066 #if SICSLOWPAN_CONF_FRAG
2067  queuebuf_init();
2068 #endif
2069 }
2070 /*--------------------------------------------------------------------*/
2071 int
2072 sicslowpan_get_last_rssi(void)
2073 {
2074  return last_rssi;
2075 }
2076 /*--------------------------------------------------------------------*/
2077 const struct network_driver sicslowpan_driver = {
2078  "sicslowpan",
2079  sicslowpan_init,
2080  input,
2081  output
2082 };
2083 /*--------------------------------------------------------------------*/
2084 /** @} */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:125
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:143
#define UIP_IP_BUF
Pointer to IP header.
Definition: uip-nd6.c:97
static uint8_t packetbuf_hdr_len
packetbuf_hdr_len is the total length of (the processed) 6lowpan headers (fragment headers...
Definition: sicslowpan.c:185
uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:107
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
Header for the Contiki/uIP interface.
static void digest_paging_dispatch(void)
Digest 6lorh headers before IPHC.
Definition: sicslowpan.c:1388
The MAC layer transmission could not be performed because of a fatal error.
Definition: mac.h:98
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:75
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:179
static int packetbuf_payload_len
The length of the payload in the Packetbuf buffer.
Definition: sicslowpan.c:193
#define UIP_ICMP_BUF
Pointer to ICMP header.
Definition: uip-nd6.c:98
void(* link_callback)(const linkaddr_t *addr, int status, int numtx)
Called by lower layers after every packet transmission.
Definition: routing.h:160
static void send_packet(linkaddr_t *dest)
This function is called by the 6lowpan code to send out a packet.
Definition: sicslowpan.c:1475
#define UIP_PROTO_HBHO
extension headers types
Definition: uip.h:1904
static void digest_6lorh_hdr(void)
Digest 6lorh headers before IPHC.
Definition: sicslowpan.c:1402
static void packet_sent(void *ptr, int status, int transmissions)
Callback function for the MAC packet sent callback.
Definition: sicslowpan.c:1444
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition: uip-ds6.c:557
A timer.
Definition: timer.h:82
const linkaddr_t linkaddr_null
The null link-layer address.
static uint8_t output(const linkaddr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
Definition: sicslowpan.c:1549
Header file for IPv6-related data structures.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:155
Configuration options for uIP.
#define sicslowpan_is_iid_16_bit_compressable(a)
check whether we can compress the IID in address &#39;a&#39; to 16 bits.
Definition: sicslowpan.h:255
static int mac_max_payload
mac_max_payload is the maimum payload space on the MAC frame.
Definition: sicslowpan.c:204
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
#define uip_is_addr_mac_addr_based(a, m)
was addr (a) forged based on the mac address m a type is uip_ipaddr_t m type is uiplladdr_t ...
Definition: uip.h:2080
static void add_paging_dispatch(uint8_t page)
Adds Paging dispatch byte.
Definition: sicslowpan.c:1366
Header file for the Packet queue buffer management
The MAC layer did not get an acknowledgement for the packet.
Definition: mac.h:88
#define UIP_LLH_LEN
The link level header length.
Definition: uipopt.h:141
static void uncompress_hdr_iphc(uint8_t *buf, uint16_t ip_len)
Uncompress IPHC (i.e., IPHC and LOWPAN_UDP) headers and put them in sicslowpan_buf.
Definition: sicslowpan.c:1059
static uint8_t uncomp_hdr_len
uncomp_hdr_len is the length of the headers before compression (if HC2 is used this includes the UDP ...
Definition: sicslowpan.c:199
The MAC layer transmission was OK.
Definition: mac.h:84
static int last_tx_status
the result of the last transmitted fragment
Definition: sicslowpan.c:214
The structure of a network driver in Contiki.
Definition: netstack.h:117
static uint8_t curr_page
The current page (RFC 4944)
Definition: sicslowpan.c:209
#define SICSLOWPAN_REASS_MAXAGE
Timeout for packet reassembly at the 6lowpan layer (should be < 60s)
Definition: uipopt.h:562
static uint8_t * hc06_ptr
pointer to the byte where to write next inline field.
Definition: sicslowpan.c:507
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Definition: uip.h:1982
Routing driver header file
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:513
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:123
The header for fragments.
Definition: sicslowpan.h:237
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
Definition: linkaddr.c:63
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition: uip.h:2107
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS
If we use IPHC compression, how many address contexts do we support.
Definition: uipopt.h:578
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1230
void(* send)(mac_callback_t sent_callback, void *ptr)
Send a packet from the packetbuf.
Definition: mac.h:69
Header file for the uIP TCP/IP stack.
static int compress_hdr_iphc(linkaddr_t *link_destaddr)
Compress IP/UDP header.
Definition: sicslowpan.c:673
static void add_6lorh_hdr(void)
Adds 6lorh headers before IPHC.
Definition: sicslowpan.c:1377
Header file for the Packet buffer (packetbuf) management
#define MAC_MAX_PAYLOAD
Maximum available size for frame headers, link layer security-related overhead, as well as 6LoWPAN pa...
Definition: sicslowpan.c:140
Include file for the Contiki low-layer network stack (NETSTACK)
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:85
#define MAC_MAX_HEADER
Maximum size of a frame header.
Definition: sicslowpan.c:148
Header file for the 6lowpan implementation (RFC4944 and draft-hui-6lowpan-hc-01) ...
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Definition: uip.h:2023
Header file for the logging system
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1777
static struct sicslowpan_addr_context * addr_context_lookup_by_number(uint8_t number)
find the context with the given number
Definition: sicslowpan.c:561
static struct sicslowpan_addr_context * addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr)
find the context corresponding to prefix ipaddr
Definition: sicslowpan.c:544
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:136
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:449
static uint8_t * packetbuf_ptr
A pointer to the packetbuf buffer.
Definition: sicslowpan.c:178
static struct sicslowpan_addr_context * context
Addresses contexts for IPHC.
Definition: sicslowpan.c:504