Contiki 3.x
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  * @{
49  */
50 
51 /**
52  * FOR HC-06 COMPLIANCE TODO:
53  * -Add compression options to UDP, currently only supports
54  * both ports compressed or both ports elided
55  *
56  * -Verify TC/FL compression works
57  *
58  * -Add stateless multicast option
59  */
60 
61 #include <string.h>
62 
63 #include "contiki.h"
64 #include "dev/watchdog.h"
65 #include "net/link-stats.h"
66 #include "net/ip/tcpip.h"
67 #include "net/ip/uip.h"
68 #include "net/ipv6/uip-ds6.h"
69 #include "net/rime/rime.h"
70 #include "net/ipv6/sicslowpan.h"
71 #include "net/netstack.h"
72 
73 #include <stdio.h>
74 
75 #define DEBUG DEBUG_NONE
76 #include "net/ip/uip-debug.h"
77 #if DEBUG
78 /* PRINTFI and PRINTFO are defined for input and output to debug one without changing the timing of the other */
79 uint8_t p;
80 #include <stdio.h>
81 #define PRINTFI(...) PRINTF(__VA_ARGS__)
82 #define PRINTFO(...) PRINTF(__VA_ARGS__)
83 #else
84 #define PRINTFI(...)
85 #define PRINTFO(...)
86 #endif /* DEBUG == 1*/
87 
88 #if UIP_LOGGING
89 #include <stdio.h>
90 void uip_log(char *msg);
91 #define UIP_LOG(m) uip_log(m)
92 #else
93 #define UIP_LOG(m)
94 #endif /* UIP_LOGGING == 1 */
95 
96 #ifndef SICSLOWPAN_COMPRESSION
97 #ifdef SICSLOWPAN_CONF_COMPRESSION
98 #define SICSLOWPAN_COMPRESSION SICSLOWPAN_CONF_COMPRESSION
99 #else
100 #define SICSLOWPAN_COMPRESSION SICSLOWPAN_COMPRESSION_IPV6
101 #endif /* SICSLOWPAN_CONF_COMPRESSION */
102 #endif /* SICSLOWPAN_COMPRESSION */
103 
104 #define GET16(ptr,index) (((uint16_t)((ptr)[index] << 8)) | ((ptr)[(index) + 1]))
105 #define SET16(ptr,index,value) do { \
106  (ptr)[index] = ((value) >> 8) & 0xff; \
107  (ptr)[index + 1] = (value) & 0xff; \
108 } while(0)
109 
110 /** \name Pointers in the packetbuf buffer
111  * @{
112  */
113 #define PACKETBUF_FRAG_PTR (packetbuf_ptr)
114 #define PACKETBUF_FRAG_DISPATCH_SIZE 0 /* 16 bit */
115 #define PACKETBUF_FRAG_TAG 2 /* 16 bit */
116 #define PACKETBUF_FRAG_OFFSET 4 /* 8 bit */
117 
118 /* define the buffer as a byte array */
119 #define PACKETBUF_IPHC_BUF ((uint8_t *)(packetbuf_ptr + packetbuf_hdr_len))
120 
121 #define PACKETBUF_HC1_PTR (packetbuf_ptr + packetbuf_hdr_len)
122 #define PACKETBUF_HC1_DISPATCH 0 /* 8 bit */
123 #define PACKETBUF_HC1_ENCODING 1 /* 8 bit */
124 #define PACKETBUF_HC1_TTL 2 /* 8 bit */
125 
126 #define PACKETBUF_HC1_HC_UDP_PTR (packetbuf_ptr + packetbuf_hdr_len)
127 #define PACKETBUF_HC1_HC_UDP_DISPATCH 0 /* 8 bit */
128 #define PACKETBUF_HC1_HC_UDP_HC1_ENCODING 1 /* 8 bit */
129 #define PACKETBUF_HC1_HC_UDP_UDP_ENCODING 2 /* 8 bit */
130 #define PACKETBUF_HC1_HC_UDP_TTL 3 /* 8 bit */
131 #define PACKETBUF_HC1_HC_UDP_PORTS 4 /* 8 bit */
132 #define PACKETBUF_HC1_HC_UDP_CHKSUM 5 /* 16 bit */
133 
134 /** \name Pointers in the sicslowpan and uip buffer
135  * @{
136  */
137 
138 /* NOTE: In the multiple-reassembly context there is only room for the header / first fragment */
139 #define SICSLOWPAN_IP_BUF(buf) ((struct uip_ip_hdr *)buf)
140 #define SICSLOWPAN_UDP_BUF(buf) ((struct uip_udp_hdr *)&buf[UIP_IPH_LEN])
141 
142 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
143 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
144 #define UIP_TCP_BUF ((struct uip_tcp_hdr *)&uip_buf[UIP_LLIPH_LEN])
145 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN])
146 /** @} */
147 
148 
149 /** \brief Maximum available size for frame headers,
150  link layer security-related overhead, as well as
151  6LoWPAN payload. */
152 #ifdef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
153 #define MAC_MAX_PAYLOAD SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
154 #else /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
155 #define MAC_MAX_PAYLOAD (127 - 2)
156 #endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
157 
158 
159 /** \brief Some MAC layers need a minimum payload, which is configurable
160  through the SICSLOWPAN_CONF_COMPRESSION_THRESHOLD option. */
161 #ifdef SICSLOWPAN_CONF_COMPRESSION_THRESHOLD
162 #define COMPRESSION_THRESHOLD SICSLOWPAN_CONF_COMPRESSION_THRESHOLD
163 #else
164 #define COMPRESSION_THRESHOLD 0
165 #endif
166 
167 /** \brief Fixed size of a frame header. This value is
168  * used in case framer returns an error or if SICSLOWPAN_USE_FIXED_HDRLEN
169  * is defined.
170  */
171 #ifndef SICSLOWPAN_FIXED_HDRLEN
172 #define SICSLOWPAN_FIXED_HDRLEN 21
173 #endif
174 
175 /** \name General variables
176  * @{
177  */
178 
179 /**
180  * A pointer to the packetbuf buffer.
181  * We initialize it to the beginning of the packetbuf buffer, then
182  * access different fields by updating the offset packetbuf_hdr_len.
183  */
184 static uint8_t *packetbuf_ptr;
185 
186 /**
187  * packetbuf_hdr_len is the total length of (the processed) 6lowpan headers
188  * (fragment headers, IPV6 or HC1, HC2, and HC1 and HC2 non compressed
189  * fields).
190  */
191 static uint8_t packetbuf_hdr_len;
192 
193 /**
194  * The length of the payload in the Packetbuf buffer.
195  * The payload is what comes after the compressed or uncompressed
196  * headers (can be the IP payload if the IP header only is compressed
197  * or the UDP payload if the UDP header is also compressed)
198  */
200 
201 /**
202  * uncomp_hdr_len is the length of the headers before compression (if HC2
203  * is used this includes the UDP header in addition to the IP header).
204  */
205 static uint8_t uncomp_hdr_len;
206 
207 /**
208  * the result of the last transmitted fragment
209  */
210 static int last_tx_status;
211 /** @} */
212 
213 
214 static int last_rssi;
215 
216 /* ----------------------------------------------------------------- */
217 /* Support for reassembling multiple packets */
218 /* ----------------------------------------------------------------- */
219 
220 #if SICSLOWPAN_CONF_FRAG
221 static uint16_t my_tag;
222 
223 /** The total length of the IPv6 packet in the sicslowpan_buf. */
224 
225 /* This needs to be defined in NBR / Nodes depending on available RAM */
226 /* and expected reassembly requirements */
227 #ifdef SICSLOWPAN_CONF_FRAGMENT_BUFFERS
228 #define SICSLOWPAN_FRAGMENT_BUFFERS SICSLOWPAN_CONF_FRAGMENT_BUFFERS
229 #else
230 #define SICSLOWPAN_FRAGMENT_BUFFERS 12
231 #endif
232 
233 /* REASS_CONTEXTS corresponds to the number of simultaneous
234  * reassemblies that can be made. NOTE: the first buffer for each
235  * reassembly is stored in the context since it can be larger than the
236  * rest of the fragments due to header compression.
237  **/
238 #ifdef SICSLOWPAN_CONF_REASS_CONTEXTS
239 #define SICSLOWPAN_REASS_CONTEXTS SICSLOWPAN_CONF_REASS_CONTEXTS
240 #else
241 #define SICSLOWPAN_REASS_CONTEXTS 2
242 #endif
243 
244 /* The size of each fragment (IP payload) for the 6lowpan fragmentation */
245 #ifdef SICSLOWPAN_CONF_FRAGMENT_SIZE
246 #define SICSLOWPAN_FRAGMENT_SIZE SICSLOWPAN_CONF_FRAGMENT_SIZE
247 #else
248 #define SICSLOWPAN_FRAGMENT_SIZE 110
249 #endif
250 
251 /* Assuming that the worst growth for uncompression is 38 bytes */
252 #define SICSLOWPAN_FIRST_FRAGMENT_SIZE (SICSLOWPAN_FRAGMENT_SIZE + 38)
253 
254 /* all information needed for reassembly */
255 struct sicslowpan_frag_info {
256  /** When reassembling, the source address of the fragments being merged */
257  linkaddr_t sender;
258  /** The destination address of the fragments being merged */
259  linkaddr_t receiver;
260  /** When reassembling, the tag in the fragments being merged. */
261  uint16_t tag;
262  /** Total length of the fragmented packet */
263  uint16_t len;
264  /** Current length of reassembled fragments */
265  uint16_t reassembled_len;
266  /** Reassembly %process %timer. */
267  struct timer reass_timer;
268 
269  /** Fragment size of first fragment */
270  uint16_t first_frag_len;
271  /** First fragment - needs a larger buffer since the size is uncompressed size
272  and we need to know total size to know when we have received last fragment. */
273  uint8_t first_frag[SICSLOWPAN_FIRST_FRAGMENT_SIZE];
274 };
275 
276 static struct sicslowpan_frag_info frag_info[SICSLOWPAN_REASS_CONTEXTS];
277 
278 struct sicslowpan_frag_buf {
279  /* the index of the frag_info */
280  uint8_t index;
281  /* Fragment offset */
282  uint8_t offset;
283  /* Length of this fragment (if zero this buffer is not allocated) */
284  uint8_t len;
285  uint8_t data[SICSLOWPAN_FRAGMENT_SIZE];
286 };
287 
288 static struct sicslowpan_frag_buf frag_buf[SICSLOWPAN_FRAGMENT_BUFFERS];
289 
290 /*---------------------------------------------------------------------------*/
291 static int
292 clear_fragments(uint8_t frag_info_index)
293 {
294  int i, clear_count;
295  clear_count = 0;
296  frag_info[frag_info_index].len = 0;
297  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
298  if(frag_buf[i].len > 0 && frag_buf[i].index == frag_info_index) {
299  /* deallocate the buffer */
300  frag_buf[i].len = 0;
301  clear_count++;
302  }
303  }
304  return clear_count;
305 }
306 /*---------------------------------------------------------------------------*/
307 static int
308 timeout_fragments(int not_context)
309 {
310  int i;
311  int count = 0;
312  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
313  if(frag_info[i].len > 0 && i != not_context &&
314  timer_expired(&frag_info[i].reass_timer)) {
315  /* This context can be freed */
316  count += clear_fragments(i);
317  }
318  }
319  return count;
320 }
321 /*---------------------------------------------------------------------------*/
322 static int
323 store_fragment(uint8_t index, uint8_t offset)
324 {
325  int i;
326  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
327  if(frag_buf[i].len == 0) {
328  /* copy over the data from packetbuf into the fragment buffer and store offset and len */
329  frag_buf[i].offset = offset; /* frag offset */
330  frag_buf[i].len = packetbuf_datalen() - packetbuf_hdr_len;
331  frag_buf[i].index = index;
332  memcpy(frag_buf[i].data, packetbuf_ptr + packetbuf_hdr_len,
334 
335  PRINTF("Fragsize: %d\n", frag_buf[i].len);
336  /* return the length of the stored fragment */
337  return frag_buf[i].len;
338  }
339  }
340  /* failed */
341  return -1;
342 }
343 /*---------------------------------------------------------------------------*/
344 /* add a new fragment to the buffer */
345 static int8_t
346 add_fragment(uint16_t tag, uint16_t frag_size, uint8_t offset)
347 {
348  int i;
349  int len;
350  int8_t found = -1;
351 
352  if(offset == 0) {
353  /* This is a first fragment - check if we can add this */
354  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
355  /* clear all fragment info with expired timer to free all fragment buffers */
356  if(frag_info[i].len > 0 && timer_expired(&frag_info[i].reass_timer)) {
357  clear_fragments(i);
358  }
359 
360  /* We use len as indication on used or not used */
361  if(found < 0 && frag_info[i].len == 0) {
362  /* We remember the first free fragment info but must continue
363  the loop to free any other expired fragment buffers. */
364  found = i;
365  }
366  }
367 
368  if(found < 0) {
369  PRINTF("*** Failed to store new fragment session - tag: %d\n", tag);
370  return -1;
371  }
372 
373  /* Found a free fragment info to store data in */
374  frag_info[found].len = frag_size;
375  frag_info[found].tag = tag;
376  linkaddr_copy(&frag_info[found].sender,
377  packetbuf_addr(PACKETBUF_ADDR_SENDER));
378  timer_set(&frag_info[found].reass_timer, SICSLOWPAN_REASS_MAXAGE * CLOCK_SECOND / 16);
379  /* first fragment can not be stored immediately but is moved into
380  the buffer while uncompressing */
381  return found;
382  }
383 
384  /* This is a N-fragment - should find the info */
385  for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
386  if(frag_info[i].tag == tag && frag_info[i].len > 0 &&
387  linkaddr_cmp(&frag_info[i].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
388  /* Tag and Sender match - this must be the correct info to store in */
389  found = i;
390  break;
391  }
392  }
393 
394  if(found < 0) {
395  /* no entry found for storing the new fragment */
396  PRINTF("*** Failed to store N-fragment - could not find session - tag: %d offset: %d\n", tag, offset);
397  return -1;
398  }
399 
400  /* i is the index of the reassembly context */
401  len = store_fragment(i, offset);
402  if(len < 0 && timeout_fragments(i) > 0) {
403  len = store_fragment(i, offset);
404  }
405  if(len > 0) {
406  frag_info[i].reassembled_len += len;
407  return i;
408  } else {
409  /* should we also clear all fragments since we failed to store
410  this fragment? */
411  PRINTF("*** Failed to store fragment - packet reassembly will fail tag:%d l\n", frag_info[i].tag);
412  return -1;
413  }
414 }
415 /*---------------------------------------------------------------------------*/
416 /* Copy all the fragments that are associated with a specific context
417  into uip */
418 static void
419 copy_frags2uip(int context)
420 {
421  int i;
422 
423  /* Copy from the fragment context info buffer first */
424  memcpy((uint8_t *)UIP_IP_BUF, (uint8_t *)frag_info[context].first_frag,
425  frag_info[context].first_frag_len);
426  for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
427  /* And also copy all matching fragments */
428  if(frag_buf[i].len > 0 && frag_buf[i].index == context) {
429  memcpy((uint8_t *)UIP_IP_BUF + (uint16_t)(frag_buf[i].offset << 3),
430  (uint8_t *)frag_buf[i].data, frag_buf[i].len);
431  }
432  }
433  /* deallocate all the fragments for this context */
434  clear_fragments(context);
435 }
436 #endif /* SICSLOWPAN_CONF_FRAG */
437 
438 /* -------------------------------------------------------------------------- */
439 
440 /*-------------------------------------------------------------------------*/
441 /* Rime Sniffer support for one single listener to enable powertrace of IP */
442 /*-------------------------------------------------------------------------*/
443 static struct rime_sniffer *callback = NULL;
444 
445 void
446 rime_sniffer_add(struct rime_sniffer *s)
447 {
448  callback = s;
449 }
450 
451 void
452 rime_sniffer_remove(struct rime_sniffer *s)
453 {
454  callback = NULL;
455 }
456 
457 static void
458 set_packet_attrs(void)
459 {
460  int c = 0;
461  /* set protocol in NETWORK_ID */
462  packetbuf_set_attr(PACKETBUF_ATTR_NETWORK_ID, UIP_IP_BUF->proto);
463 
464  /* assign values to the channel attribute (port or type + code) */
465  if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
466  c = UIP_UDP_BUF->srcport;
467  if(UIP_UDP_BUF->destport < c) {
468  c = UIP_UDP_BUF->destport;
469  }
470  } else if(UIP_IP_BUF->proto == UIP_PROTO_TCP) {
471  c = UIP_TCP_BUF->srcport;
472  if(UIP_TCP_BUF->destport < c) {
473  c = UIP_TCP_BUF->destport;
474  }
475  } else if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6) {
476  c = UIP_ICMP_BUF->type << 8 | UIP_ICMP_BUF->icode;
477  }
478 
479  packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, c);
480 
481 /* if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { */
482 /* own = 1; */
483 /* } */
484 
485 }
486 
487 
488 
489 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
490 /** \name HC06 specific variables
491  * @{
492  */
493 
494 /** Addresses contexts for IPHC. */
495 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
496 static struct sicslowpan_addr_context
497 addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
498 #endif
499 
500 /** pointer to an address context. */
502 
503 /** pointer to the byte where to write next inline field. */
504 static uint8_t *hc06_ptr;
505 
506 /* Uncompression of linklocal */
507 /* 0 -> 16 bytes from packet */
508 /* 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet */
509 /* 2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet */
510 /* 3 -> 2 bytes from prefix - infer 8 bytes from lladdr */
511 /* NOTE: => the uncompress function does change 0xf to 0x10 */
512 /* NOTE: 0x00 => no-autoconfig => unspecified */
513 const uint8_t unc_llconf[] = {0x0f,0x28,0x22,0x20};
514 
515 /* Uncompression of ctx-based */
516 /* 0 -> 0 bits from packet [unspecified / reserved] */
517 /* 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet */
518 /* 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX + 2 from packet */
519 /* 3 -> 8 bytes from prefix - infer 8 bytes from lladdr */
520 const uint8_t unc_ctxconf[] = {0x00,0x88,0x82,0x80};
521 
522 /* Uncompression of ctx-based */
523 /* 0 -> 0 bits from packet */
524 /* 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet */
525 /* 2 -> 2 bytes from prefix - zeroes + 3 from packet */
526 /* 3 -> 2 bytes from prefix - infer 1 bytes from lladdr */
527 const uint8_t unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
528 
529 /* Link local prefix */
530 const uint8_t llprefix[] = {0xfe, 0x80};
531 
532 /* TTL uncompression values */
533 static const uint8_t ttl_values[] = {0, 1, 64, 255};
534 
535 /*--------------------------------------------------------------------*/
536 /** \name IPHC related functions
537  * @{ */
538 /*--------------------------------------------------------------------*/
539 /** \brief find the context corresponding to prefix ipaddr */
540 static struct sicslowpan_addr_context*
542 {
543 /* Remove code to avoid warnings and save flash if no context is used */
544 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
545  int i;
546  for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
547  if((addr_contexts[i].used == 1) &&
548  uip_ipaddr_prefixcmp(&addr_contexts[i].prefix, ipaddr, 64)) {
549  return &addr_contexts[i];
550  }
551  }
552 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
553  return NULL;
554 }
555 /*--------------------------------------------------------------------*/
556 /** \brief find the context with the given number */
557 static struct sicslowpan_addr_context*
559 {
560 /* Remove code to avoid warnings and save flash if no context is used */
561 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
562  int i;
563  for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
564  if((addr_contexts[i].used == 1) &&
565  addr_contexts[i].number == number) {
566  return &addr_contexts[i];
567  }
568  }
569 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
570  return NULL;
571 }
572 /*--------------------------------------------------------------------*/
573 static uint8_t
574 compress_addr_64(uint8_t bitpos, uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
575 {
576  if(uip_is_addr_mac_addr_based(ipaddr, lladdr)) {
577  return 3 << bitpos; /* 0-bits */
578  } else if(sicslowpan_is_iid_16_bit_compressable(ipaddr)) {
579  /* compress IID to 16 bits xxxx::0000:00ff:fe00:XXXX */
580  memcpy(hc06_ptr, &ipaddr->u16[7], 2);
581  hc06_ptr += 2;
582  return 2 << bitpos; /* 16-bits */
583  } else {
584  /* do not compress IID => xxxx::IID */
585  memcpy(hc06_ptr, &ipaddr->u16[4], 8);
586  hc06_ptr += 8;
587  return 1 << bitpos; /* 64-bits */
588  }
589 }
590 
591 /*-------------------------------------------------------------------- */
592 /* Uncompress addresses based on a prefix and a postfix with zeroes in
593  * between. If the postfix is zero in length it will use the link address
594  * to configure the IP address (autoconf style).
595  * pref_post_count takes a byte where the first nibble specify prefix count
596  * and the second postfix count (NOTE: 15/0xf => 16 bytes copy).
597  */
598 static void
599 uncompress_addr(uip_ipaddr_t *ipaddr, uint8_t const prefix[],
600  uint8_t pref_post_count, uip_lladdr_t *lladdr)
601 {
602  uint8_t prefcount = pref_post_count >> 4;
603  uint8_t postcount = pref_post_count & 0x0f;
604  /* full nibble 15 => 16 */
605  prefcount = prefcount == 15 ? 16 : prefcount;
606  postcount = postcount == 15 ? 16 : postcount;
607 
608  PRINTF("Uncompressing %d + %d => ", prefcount, postcount);
609 
610  if(prefcount > 0) {
611  memcpy(ipaddr, prefix, prefcount);
612  }
613  if(prefcount + postcount < 16) {
614  memset(&ipaddr->u8[prefcount], 0, 16 - (prefcount + postcount));
615  }
616  if(postcount > 0) {
617  memcpy(&ipaddr->u8[16 - postcount], hc06_ptr, postcount);
618  if(postcount == 2 && prefcount < 11) {
619  /* 16 bits uncompression => 0000:00ff:fe00:XXXX */
620  ipaddr->u8[11] = 0xff;
621  ipaddr->u8[12] = 0xfe;
622  }
623  hc06_ptr += postcount;
624  } else if (prefcount > 0) {
625  /* no IID based configuration if no prefix and no data => unspec */
626  uip_ds6_set_addr_iid(ipaddr, lladdr);
627  }
628 
629  PRINT6ADDR(ipaddr);
630  PRINTF("\n");
631 }
632 
633 /*--------------------------------------------------------------------*/
634 /**
635  * \brief Compress IP/UDP header
636  *
637  * This function is called by the 6lowpan code to create a compressed
638  * 6lowpan packet in the packetbuf buffer from a full IPv6 packet in the
639  * uip_buf buffer.
640  *
641  *
642  * IPHC (RFC 6282)\n
643  * http://tools.ietf.org/html/
644  *
645  * \note We do not support ISA100_UDP header compression
646  *
647  * For LOWPAN_UDP compression, we either compress both ports or none.
648  * General format with LOWPAN_UDP compression is
649  * \verbatim
650  * 1 2 3
651  * 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
652  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
653  * |0|1|1|TF |N|HLI|C|S|SAM|M|D|DAM| SCI | DCI | comp. IPv6 hdr|
654  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
655  * | compressed IPv6 fields ..... |
656  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
657  * | LOWPAN_UDP | non compressed UDP fields ... |
658  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
659  * | L4 data ... |
660  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
661  * \endverbatim
662  * \note The context number 00 is reserved for the link local prefix.
663  * For unicast addresses, if we cannot compress the prefix, we neither
664  * compress the IID.
665  * \param link_destaddr L2 destination address, needed to compress IP
666  * dest
667  */
668 static void
669 compress_hdr_iphc(linkaddr_t *link_destaddr)
670 {
671  uint8_t tmp, iphc0, iphc1;
672 #if DEBUG
673  { uint16_t ndx;
674  PRINTF("before compression (%d): ", UIP_IP_BUF->len[1]);
675  for(ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
676  uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
677  PRINTF("%02x", data);
678  }
679  PRINTF("\n");
680  }
681 #endif
682 
683  hc06_ptr = packetbuf_ptr + 2;
684  /*
685  * As we copy some bit-length fields, in the IPHC encoding bytes,
686  * we sometimes use |=
687  * If the field is 0, and the current bit value in memory is 1,
688  * this does not work. We therefore reset the IPHC encoding here
689  */
690 
691  iphc0 = SICSLOWPAN_DISPATCH_IPHC;
692  iphc1 = 0;
693  PACKETBUF_IPHC_BUF[2] = 0; /* might not be used - but needs to be cleared */
694 
695  /*
696  * Address handling needs to be made first since it might
697  * cause an extra byte with [ SCI | DCI ]
698  *
699  */
700 
701 
702  /* check if dest context exists (for allocating third byte) */
703  /* TODO: fix this so that it remembers the looked up values for
704  avoiding two lookups - or set the lookup values immediately */
705  if(addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr) != NULL ||
707  /* set context flag and increase hc06_ptr */
708  PRINTF("IPHC: compressing dest or src ipaddr - setting CID\n");
709  iphc1 |= SICSLOWPAN_IPHC_CID;
710  hc06_ptr++;
711  }
712 
713  /*
714  * Traffic class, flow label
715  * If flow label is 0, compress it. If traffic class is 0, compress it
716  * We have to process both in the same time as the offset of traffic class
717  * depends on the presence of version and flow label
718  */
719 
720  /* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
721 
722  tmp = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
723  tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
724 
725  if(((UIP_IP_BUF->tcflow & 0x0F) == 0) &&
726  (UIP_IP_BUF->flow == 0)) {
727  /* flow label can be compressed */
728  iphc0 |= SICSLOWPAN_IPHC_FL_C;
729  if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
730  ((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
731  /* compress (elide) all */
732  iphc0 |= SICSLOWPAN_IPHC_TC_C;
733  } else {
734  /* compress only the flow label */
735  *hc06_ptr = tmp;
736  hc06_ptr += 1;
737  }
738  } else {
739  /* Flow label cannot be compressed */
740  if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
741  ((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
742  /* compress only traffic class */
743  iphc0 |= SICSLOWPAN_IPHC_TC_C;
744  *hc06_ptr = (tmp & 0xc0) |
745  (UIP_IP_BUF->tcflow & 0x0F);
746  memcpy(hc06_ptr + 1, &UIP_IP_BUF->flow, 2);
747  hc06_ptr += 3;
748  } else {
749  /* compress nothing */
750  memcpy(hc06_ptr, &UIP_IP_BUF->vtc, 4);
751  /* but replace the top byte with the new ECN | DSCP format*/
752  *hc06_ptr = tmp;
753  hc06_ptr += 4;
754  }
755  }
756 
757  /* Note that the payload length is always compressed */
758 
759  /* Next header. We compress it if UDP */
760 #if UIP_CONF_UDP || UIP_CONF_ROUTER
761  if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
762  iphc0 |= SICSLOWPAN_IPHC_NH_C;
763  }
764 #endif /*UIP_CONF_UDP*/
765 
766  if ((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
767  *hc06_ptr = UIP_IP_BUF->proto;
768  hc06_ptr += 1;
769  }
770 
771  /*
772  * Hop limit
773  * if 1: compress, encoding is 01
774  * if 64: compress, encoding is 10
775  * if 255: compress, encoding is 11
776  * else do not compress
777  */
778  switch(UIP_IP_BUF->ttl) {
779  case 1:
780  iphc0 |= SICSLOWPAN_IPHC_TTL_1;
781  break;
782  case 64:
783  iphc0 |= SICSLOWPAN_IPHC_TTL_64;
784  break;
785  case 255:
786  iphc0 |= SICSLOWPAN_IPHC_TTL_255;
787  break;
788  default:
789  *hc06_ptr = UIP_IP_BUF->ttl;
790  hc06_ptr += 1;
791  break;
792  }
793 
794  /* source address - cannot be multicast */
795  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
796  PRINTF("IPHC: compressing unspecified - setting SAC\n");
797  iphc1 |= SICSLOWPAN_IPHC_SAC;
798  iphc1 |= SICSLOWPAN_IPHC_SAM_00;
799  } else if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr))
800  != NULL) {
801  /* elide the prefix - indicate by CID and set context + SAC */
802  PRINTF("IPHC: compressing src with context - setting CID & SAC ctx: %d\n",
803  context->number);
804  iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
805  PACKETBUF_IPHC_BUF[2] |= context->number << 4;
806  /* compession compare with this nodes address (source) */
807 
808  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
809  &UIP_IP_BUF->srcipaddr, &uip_lladdr);
810  /* No context found for this address */
811  } else if(uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) &&
812  UIP_IP_BUF->destipaddr.u16[1] == 0 &&
813  UIP_IP_BUF->destipaddr.u16[2] == 0 &&
814  UIP_IP_BUF->destipaddr.u16[3] == 0) {
815  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
816  &UIP_IP_BUF->srcipaddr, &uip_lladdr);
817  } else {
818  /* send the full address => SAC = 0, SAM = 00 */
819  iphc1 |= SICSLOWPAN_IPHC_SAM_00; /* 128-bits */
820  memcpy(hc06_ptr, &UIP_IP_BUF->srcipaddr.u16[0], 16);
821  hc06_ptr += 16;
822  }
823 
824  /* dest address*/
825  if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
826  /* Address is multicast, try to compress */
827  iphc1 |= SICSLOWPAN_IPHC_M;
828  if(sicslowpan_is_mcast_addr_compressable8(&UIP_IP_BUF->destipaddr)) {
829  iphc1 |= SICSLOWPAN_IPHC_DAM_11;
830  /* use last byte */
831  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[15];
832  hc06_ptr += 1;
833  } else if(sicslowpan_is_mcast_addr_compressable32(&UIP_IP_BUF->destipaddr)) {
834  iphc1 |= SICSLOWPAN_IPHC_DAM_10;
835  /* second byte + the last three */
836  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
837  memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[13], 3);
838  hc06_ptr += 4;
839  } else if(sicslowpan_is_mcast_addr_compressable48(&UIP_IP_BUF->destipaddr)) {
840  iphc1 |= SICSLOWPAN_IPHC_DAM_01;
841  /* second byte + the last five */
842  *hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
843  memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[11], 5);
844  hc06_ptr += 6;
845  } else {
846  iphc1 |= SICSLOWPAN_IPHC_DAM_00;
847  /* full address */
848  memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u8[0], 16);
849  hc06_ptr += 16;
850  }
851  } else {
852  /* Address is unicast, try to compress */
853  if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr)) != NULL) {
854  /* elide the prefix */
855  iphc1 |= SICSLOWPAN_IPHC_DAC;
856  PACKETBUF_IPHC_BUF[2] |= context->number;
857  /* compession compare with link adress (destination) */
858 
859  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
860  &UIP_IP_BUF->destipaddr,
861  (uip_lladdr_t *)link_destaddr);
862  /* No context found for this address */
863  } else if(uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) &&
864  UIP_IP_BUF->destipaddr.u16[1] == 0 &&
865  UIP_IP_BUF->destipaddr.u16[2] == 0 &&
866  UIP_IP_BUF->destipaddr.u16[3] == 0) {
867  iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
868  &UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
869  } else {
870  /* send the full address */
871  iphc1 |= SICSLOWPAN_IPHC_DAM_00; /* 128-bits */
872  memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u16[0], 16);
873  hc06_ptr += 16;
874  }
875  }
876 
877  uncomp_hdr_len = UIP_IPH_LEN;
878 
879 #if UIP_CONF_UDP || UIP_CONF_ROUTER
880  /* UDP header compression */
881  if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
882  PRINTF("IPHC: Uncompressed UDP ports on send side: %x, %x\n",
883  UIP_HTONS(UIP_UDP_BUF->srcport), UIP_HTONS(UIP_UDP_BUF->destport));
884  /* Mask out the last 4 bits can be used as a mask */
885  if(((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
886  ((UIP_HTONS(UIP_UDP_BUF->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
887  /* we can compress 12 bits of both source and dest */
888  *hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_11;
889  PRINTF("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
890  *(hc06_ptr + 1) =
891  (uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
892  SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
893  (uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
894  SICSLOWPAN_UDP_4_BIT_PORT_MIN));
895  hc06_ptr += 2;
896  } else if((UIP_HTONS(UIP_UDP_BUF->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
897  /* we can compress 8 bits of dest, leave source. */
898  *hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_01;
899  PRINTF("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
900  memcpy(hc06_ptr + 1, &UIP_UDP_BUF->srcport, 2);
901  *(hc06_ptr + 3) =
902  (uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
903  SICSLOWPAN_UDP_8_BIT_PORT_MIN));
904  hc06_ptr += 4;
905  } else if((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
906  /* we can compress 8 bits of src, leave dest. Copy compressed port */
907  *hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_10;
908  PRINTF("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *hc06_ptr);
909  *(hc06_ptr + 1) =
910  (uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
911  SICSLOWPAN_UDP_8_BIT_PORT_MIN));
912  memcpy(hc06_ptr + 2, &UIP_UDP_BUF->destport, 2);
913  hc06_ptr += 4;
914  } else {
915  /* we cannot compress. Copy uncompressed ports, full checksum */
916  *hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_00;
917  PRINTF("IPHC: cannot compress headers\n");
918  memcpy(hc06_ptr + 1, &UIP_UDP_BUF->srcport, 4);
919  hc06_ptr += 5;
920  }
921  /* always inline the checksum */
922  if(1) {
923  memcpy(hc06_ptr, &UIP_UDP_BUF->udpchksum, 2);
924  hc06_ptr += 2;
925  }
926  uncomp_hdr_len += UIP_UDPH_LEN;
927  }
928 #endif /*UIP_CONF_UDP*/
929 
930  /* before the packetbuf_hdr_len operation */
931  PACKETBUF_IPHC_BUF[0] = iphc0;
932  PACKETBUF_IPHC_BUF[1] = iphc1;
933 
934  packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
935  return;
936 }
937 
938 /*--------------------------------------------------------------------*/
939 /**
940  * \brief Uncompress IPHC (i.e., IPHC and LOWPAN_UDP) headers and put
941  * them in sicslowpan_buf
942  *
943  * This function is called by the input function when the dispatch is
944  * IPHC.
945  * We %process the packet in the packetbuf buffer, uncompress the header
946  * fields, and copy the result in the sicslowpan buffer.
947  * At the end of the decompression, packetbuf_hdr_len and uncompressed_hdr_len
948  * are set to the appropriate values
949  *
950  * \param buf Pointer to the buffer to uncompress the packet into.
951  * \param ip_len Equal to 0 if the packet is not a fragment (IP length
952  * is then inferred from the L2 length), non 0 if the packet is a 1st
953  * fragment.
954  */
955 static void
956 uncompress_hdr_iphc(uint8_t *buf, uint16_t ip_len)
957 {
958  uint8_t tmp, iphc0, iphc1;
959  /* at least two byte will be used for the encoding */
960  hc06_ptr = packetbuf_ptr + packetbuf_hdr_len + 2;
961 
962  iphc0 = PACKETBUF_IPHC_BUF[0];
963  iphc1 = PACKETBUF_IPHC_BUF[1];
964 
965  /* another if the CID flag is set */
966  if(iphc1 & SICSLOWPAN_IPHC_CID) {
967  PRINTF("IPHC: CID flag set - increase header with one\n");
968  hc06_ptr++;
969  }
970 
971  /* Traffic class and flow label */
972  if((iphc0 & SICSLOWPAN_IPHC_FL_C) == 0) {
973  /* Flow label are carried inline */
974  if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
975  /* Traffic class is carried inline */
976  memcpy(&SICSLOWPAN_IP_BUF(buf)->tcflow, hc06_ptr + 1, 3);
977  tmp = *hc06_ptr;
978  hc06_ptr += 4;
979  /* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
980  /* set version, pick highest DSCP bits and set in vtc */
981  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((tmp >> 2) & 0x0f);
982  /* ECN rolled down two steps + lowest DSCP bits at top two bits */
983  SICSLOWPAN_IP_BUF(buf)->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
984  (SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f);
985  } else {
986  /* Traffic class is compressed (set version and no TC)*/
987  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
988  /* highest flow label bits + ECN bits */
989  SICSLOWPAN_IP_BUF(buf)->tcflow = (*hc06_ptr & 0x0F) |
990  ((*hc06_ptr >> 2) & 0x30);
991  memcpy(&SICSLOWPAN_IP_BUF(buf)->flow, hc06_ptr + 1, 2);
992  hc06_ptr += 3;
993  }
994  } else {
995  /* Version is always 6! */
996  /* Version and flow label are compressed */
997  if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
998  /* Traffic class is inline */
999  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*hc06_ptr >> 2) & 0x0f);
1000  SICSLOWPAN_IP_BUF(buf)->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30);
1001  SICSLOWPAN_IP_BUF(buf)->flow = 0;
1002  hc06_ptr += 1;
1003  } else {
1004  /* Traffic class is compressed */
1005  SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1006  SICSLOWPAN_IP_BUF(buf)->tcflow = 0;
1007  SICSLOWPAN_IP_BUF(buf)->flow = 0;
1008  }
1009  }
1010 
1011  /* Next Header */
1012  if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
1013  /* Next header is carried inline */
1014  SICSLOWPAN_IP_BUF(buf)->proto = *hc06_ptr;
1015  PRINTF("IPHC: next header inline: %d\n", SICSLOWPAN_IP_BUF(buf)->proto);
1016  hc06_ptr += 1;
1017  }
1018 
1019  /* Hop limit */
1020  if((iphc0 & 0x03) != SICSLOWPAN_IPHC_TTL_I) {
1021  SICSLOWPAN_IP_BUF(buf)->ttl = ttl_values[iphc0 & 0x03];
1022  } else {
1023  SICSLOWPAN_IP_BUF(buf)->ttl = *hc06_ptr;
1024  hc06_ptr += 1;
1025  }
1026 
1027  /* put the source address compression mode SAM in the tmp var */
1028  tmp = ((iphc1 & SICSLOWPAN_IPHC_SAM_11) >> SICSLOWPAN_IPHC_SAM_BIT) & 0x03;
1029 
1030  /* context based compression */
1031  if(iphc1 & SICSLOWPAN_IPHC_SAC) {
1032  uint8_t sci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
1033  PACKETBUF_IPHC_BUF[2] >> 4 : 0;
1034 
1035  /* Source address - check context != NULL only if SAM bits are != 0*/
1036  if (tmp != 0) {
1037  context = addr_context_lookup_by_number(sci);
1038  if(context == NULL) {
1039  PRINTF("sicslowpan uncompress_hdr: error context not found\n");
1040  return;
1041  }
1042  }
1043  /* if tmp == 0 we do not have a context and therefore no prefix */
1044  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr,
1045  tmp != 0 ? context->prefix : NULL, unc_ctxconf[tmp],
1046  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1047  } else {
1048  /* no compression and link local */
1049  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr, llprefix, unc_llconf[tmp],
1050  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
1051  }
1052 
1053  /* Destination address */
1054  /* put the destination address compression mode into tmp */
1055  tmp = ((iphc1 & SICSLOWPAN_IPHC_DAM_11) >> SICSLOWPAN_IPHC_DAM_BIT) & 0x03;
1056 
1057  /* multicast compression */
1058  if(iphc1 & SICSLOWPAN_IPHC_M) {
1059  /* context based multicast compression */
1060  if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1061  /* TODO: implement this */
1062  } else {
1063  /* non-context based multicast compression - */
1064  /* DAM_00: 128 bits */
1065  /* DAM_01: 48 bits FFXX::00XX:XXXX:XXXX */
1066  /* DAM_10: 32 bits FFXX::00XX:XXXX */
1067  /* DAM_11: 8 bits FF02::00XX */
1068  uint8_t prefix[] = {0xff, 0x02};
1069  if(tmp > 0 && tmp < 3) {
1070  prefix[1] = *hc06_ptr;
1071  hc06_ptr++;
1072  }
1073 
1074  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, prefix,
1075  unc_mxconf[tmp], NULL);
1076  }
1077  } else {
1078  /* no multicast */
1079  /* Context based */
1080  if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1081  uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
1082  context = addr_context_lookup_by_number(dci);
1083 
1084  /* all valid cases below need the context! */
1085  if(context == NULL) {
1086  PRINTF("sicslowpan uncompress_hdr: error context not found\n");
1087  return;
1088  }
1089  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, context->prefix,
1090  unc_ctxconf[tmp],
1091  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1092  } else {
1093  /* not context based => link local M = 0, DAC = 0 - same as SAC */
1094  uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, llprefix,
1095  unc_llconf[tmp],
1096  (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
1097  }
1098  }
1099  uncomp_hdr_len += UIP_IPH_LEN;
1100 
1101  /* Next header processing - continued */
1102  if((iphc0 & SICSLOWPAN_IPHC_NH_C)) {
1103  /* The next header is compressed, NHC is following */
1104  if((*hc06_ptr & SICSLOWPAN_NHC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) {
1105  uint8_t checksum_compressed;
1106  SICSLOWPAN_IP_BUF(buf)->proto = UIP_PROTO_UDP;
1107  checksum_compressed = *hc06_ptr & SICSLOWPAN_NHC_UDP_CHECKSUMC;
1108  PRINTF("IPHC: Incoming header value: %i\n", *hc06_ptr);
1109  switch(*hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
1110  case SICSLOWPAN_NHC_UDP_CS_P_00:
1111  /* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
1112  memcpy(&SICSLOWPAN_UDP_BUF(buf)->srcport, hc06_ptr + 1, 2);
1113  memcpy(&SICSLOWPAN_UDP_BUF(buf)->destport, hc06_ptr + 3, 2);
1114  PRINTF("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n",
1115  UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->srcport),
1116  UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->destport));
1117  hc06_ptr += 5;
1118  break;
1119 
1120  case SICSLOWPAN_NHC_UDP_CS_P_01:
1121  /* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
1122  PRINTF("IPHC: Decompressing destination\n");
1123  memcpy(&SICSLOWPAN_UDP_BUF(buf)->srcport, hc06_ptr + 1, 2);
1124  SICSLOWPAN_UDP_BUF(buf)->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
1125  PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
1126  UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->destport));
1127  hc06_ptr += 4;
1128  break;
1129 
1130  case SICSLOWPAN_NHC_UDP_CS_P_10:
1131  /* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit inline*/
1132  PRINTF("IPHC: Decompressing source\n");
1133  SICSLOWPAN_UDP_BUF(buf)->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
1134  (*(hc06_ptr + 1)));
1135  memcpy(&SICSLOWPAN_UDP_BUF(buf)->destport, hc06_ptr + 2, 2);
1136  PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
1137  UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->destport));
1138  hc06_ptr += 4;
1139  break;
1140 
1141  case SICSLOWPAN_NHC_UDP_CS_P_11:
1142  /* 1 byte for NHC, 1 byte for ports */
1143  SICSLOWPAN_UDP_BUF(buf)->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1144  (*(hc06_ptr + 1) >> 4));
1145  SICSLOWPAN_UDP_BUF(buf)->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1146  ((*(hc06_ptr + 1)) & 0x0F));
1147  PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
1148  UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->destport));
1149  hc06_ptr += 2;
1150  break;
1151 
1152  default:
1153  PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n");
1154  return;
1155  }
1156  if(!checksum_compressed) { /* has_checksum, default */
1157  memcpy(&SICSLOWPAN_UDP_BUF(buf)->udpchksum, hc06_ptr, 2);
1158  hc06_ptr += 2;
1159  PRINTF("IPHC: sicslowpan uncompress_hdr: checksum included\n");
1160  } else {
1161  PRINTF("IPHC: sicslowpan uncompress_hdr: checksum *NOT* included\n");
1162  }
1163  uncomp_hdr_len += UIP_UDPH_LEN;
1164  }
1165  }
1166 
1167  packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
1168 
1169  /* IP length field. */
1170  if(ip_len == 0) {
1171  int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
1172  /* This is not a fragmented packet */
1173  SICSLOWPAN_IP_BUF(buf)->len[0] = len >> 8;
1174  SICSLOWPAN_IP_BUF(buf)->len[1] = len & 0x00FF;
1175  } else {
1176  /* This is a 1st fragment */
1177  SICSLOWPAN_IP_BUF(buf)->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
1178  SICSLOWPAN_IP_BUF(buf)->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
1179  }
1180 
1181  /* length field in UDP header */
1182  if(SICSLOWPAN_IP_BUF(buf)->proto == UIP_PROTO_UDP) {
1183  memcpy(&SICSLOWPAN_UDP_BUF(buf)->udplen, &SICSLOWPAN_IP_BUF(buf)->len[0], 2);
1184  }
1185 
1186  return;
1187 }
1188 /** @} */
1189 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
1190 
1191 /*--------------------------------------------------------------------*/
1192 /** \name IPv6 dispatch "compression" function
1193  * @{ */
1194 /*--------------------------------------------------------------------*/
1195 /* \brief Packets "Compression" when only IPv6 dispatch is used
1196  *
1197  * There is no compression in this case, all fields are sent
1198  * inline. We just add the IPv6 dispatch byte before the packet.
1199  * \verbatim
1200  * 0 1 2 3
1201  * 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
1202  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1203  * | IPv6 Dsp | IPv6 header and payload ...
1204  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1205  * \endverbatim
1206  */
1207 static void
1208 compress_hdr_ipv6(linkaddr_t *link_destaddr)
1209 {
1210  *packetbuf_ptr = SICSLOWPAN_DISPATCH_IPV6;
1211  packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
1212  memcpy(packetbuf_ptr + packetbuf_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
1213  packetbuf_hdr_len += UIP_IPH_LEN;
1214  uncomp_hdr_len += UIP_IPH_LEN;
1215  return;
1216 }
1217 /** @} */
1218 
1219 /*--------------------------------------------------------------------*/
1220 /** \name Input/output functions common to all compression schemes
1221  * @{ */
1222 /*--------------------------------------------------------------------*/
1223 /**
1224  * Callback function for the MAC packet sent callback
1225  */
1226 static void
1227 packet_sent(void *ptr, int status, int transmissions)
1228 {
1229  uip_ds6_link_neighbor_callback(status, transmissions);
1230 
1231  if(callback != NULL) {
1232  callback->output_callback(status);
1233  }
1234  last_tx_status = status;
1235 }
1236 /*--------------------------------------------------------------------*/
1237 /**
1238  * \brief This function is called by the 6lowpan code to send out a
1239  * packet.
1240  * \param dest the link layer destination address of the packet
1241  */
1242 static void
1243 send_packet(linkaddr_t *dest)
1244 {
1245  /* Set the link layer destination address for the packet as a
1246  * packetbuf attribute. The MAC layer can access the destination
1247  * address with the function packetbuf_addr(PACKETBUF_ADDR_RECEIVER).
1248  */
1249  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest);
1250 
1251 #if NETSTACK_CONF_BRIDGE_MODE
1252  /* This needs to be explicitly set here for bridge mode to work */
1253  packetbuf_set_addr(PACKETBUF_ADDR_SENDER,(void*)&uip_lladdr);
1254 #endif
1255 
1256  /* Provide a callback function to receive the result of
1257  a packet transmission. */
1258  NETSTACK_LLSEC.send(&packet_sent, NULL);
1259 
1260  /* If we are sending multiple packets in a row, we need to let the
1261  watchdog know that we are still alive. */
1263 }
1264 /*--------------------------------------------------------------------*/
1265 /** \brief Take an IP packet and format it to be sent on an 802.15.4
1266  * network using 6lowpan.
1267  * \param localdest The MAC address of the destination
1268  *
1269  * The IP packet is initially in uip_buf. Its header is compressed
1270  * and if necessary it is fragmented. The resulting
1271  * packet/fragments are put in packetbuf and delivered to the 802.15.4
1272  * MAC.
1273  */
1274 static uint8_t
1275 output(const uip_lladdr_t *localdest)
1276 {
1277  int framer_hdrlen;
1278  int max_payload;
1279 
1280  /* The MAC address of the destination of the packet */
1281  linkaddr_t dest;
1282 
1283  /* init */
1284  uncomp_hdr_len = 0;
1285  packetbuf_hdr_len = 0;
1286 
1287  /* reset packetbuf buffer */
1288  packetbuf_clear();
1290 
1291  if(callback) {
1292  /* call the attribution when the callback comes, but set attributes
1293  here ! */
1294  set_packet_attrs();
1295  }
1296 
1297 #if PACKETBUF_WITH_PACKET_TYPE
1298 #define TCP_FIN 0x01
1299 #define TCP_ACK 0x10
1300 #define TCP_CTL 0x3f
1301  /* Set stream mode for all TCP packets, except FIN packets. */
1302  if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
1303  (UIP_TCP_BUF->flags & TCP_FIN) == 0 &&
1304  (UIP_TCP_BUF->flags & TCP_CTL) != TCP_ACK) {
1305  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
1306  PACKETBUF_ATTR_PACKET_TYPE_STREAM);
1307  } else if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
1308  (UIP_TCP_BUF->flags & TCP_FIN) == TCP_FIN) {
1309  packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
1310  PACKETBUF_ATTR_PACKET_TYPE_STREAM_END);
1311  }
1312 #endif
1313 
1314  /*
1315  * The destination address will be tagged to each outbound
1316  * packet. If the argument localdest is NULL, we are sending a
1317  * broadcast packet.
1318  */
1319  if(localdest == NULL) {
1320  linkaddr_copy(&dest, &linkaddr_null);
1321  } else {
1322  linkaddr_copy(&dest, (const linkaddr_t *)localdest);
1323  }
1324 
1325  PRINTFO("sicslowpan output: sending packet len %d\n", uip_len);
1326 
1328  /* Try to compress the headers */
1329 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
1330  compress_hdr_ipv6(&dest);
1331 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
1332 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
1333  compress_hdr_iphc(&dest);
1334 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
1335  } else {
1336  compress_hdr_ipv6(&dest);
1337  }
1338  PRINTFO("sicslowpan output: header of len %d\n", packetbuf_hdr_len);
1339 
1340  /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_RDC.
1341  * We calculate it here only to make a better decision of whether the outgoing packet
1342  * needs to be fragmented or not. */
1343 #ifndef SICSLOWPAN_USE_FIXED_HDRLEN
1344  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
1345  framer_hdrlen = NETSTACK_FRAMER.length();
1346  if(framer_hdrlen < 0) {
1347  /* Framing failed, we assume the maximum header length */
1348  framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN;
1349  }
1350 #else /* USE_FRAMER_HDRLEN */
1351  framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN;
1352 #endif /* USE_FRAMER_HDRLEN */
1353 
1354  max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
1355  if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) {
1356 #if SICSLOWPAN_CONF_FRAG
1357  /* Number of bytes processed. */
1358  uint16_t processed_ip_out_len;
1359 
1360  struct queuebuf *q;
1361  uint16_t frag_tag;
1362 
1363  /*
1364  * The outbound IPv6 packet is too large to fit into a single 15.4
1365  * packet, so we fragment it into multiple packets and send them.
1366  * The first fragment contains frag1 dispatch, then
1367  * IPv6/IPHC/HC_UDP dispatchs/headers.
1368  * The following fragments contain only the fragn dispatch.
1369  */
1370  int estimated_fragments = ((int)uip_len) / (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
1371  int freebuf = queuebuf_numfree() - 1;
1372  PRINTFO("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len, estimated_fragments, freebuf);
1373  if(freebuf < estimated_fragments) {
1374  PRINTFO("Dropping packet, not enough free bufs\n");
1375  return 0;
1376  }
1377 
1378  PRINTFO("Fragmentation sending packet len %d\n", uip_len);
1379 
1380  /* Create 1st Fragment */
1381  PRINTFO("sicslowpan output: 1rst fragment ");
1382 
1383  /* Reset last tx status to ok in case the fragment transmissions are deferred */
1385 
1386  /* move IPHC/IPv6 header */
1387  memmove(packetbuf_ptr + SICSLOWPAN_FRAG1_HDR_LEN, packetbuf_ptr, packetbuf_hdr_len);
1388 
1389  /*
1390  * FRAG1 dispatch + header
1391  * Note that the length is in units of 8 bytes
1392  */
1393 /* PACKETBUF_FRAG_BUF->dispatch_size = */
1394 /* uip_htons((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len); */
1395  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1396  ((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len));
1397  frag_tag = my_tag++;
1398  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG, frag_tag);
1399 
1400  /* Copy payload and send */
1401  packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
1402  packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8;
1403  PRINTFO("(len %d, tag %d)\n", packetbuf_payload_len, frag_tag);
1404  memcpy(packetbuf_ptr + packetbuf_hdr_len,
1406  packetbuf_set_datalen(packetbuf_payload_len + packetbuf_hdr_len);
1407  q = queuebuf_new_from_packetbuf();
1408  if(q == NULL) {
1409  PRINTFO("could not allocate queuebuf for first fragment, dropping packet\n");
1410  return 0;
1411  }
1412  send_packet(&dest);
1413  queuebuf_to_packetbuf(q);
1414  queuebuf_free(q);
1415  q = NULL;
1416 
1417  /* Check tx result. */
1418  if((last_tx_status == MAC_TX_COLLISION) ||
1419  (last_tx_status == MAC_TX_ERR) ||
1420  (last_tx_status == MAC_TX_ERR_FATAL)) {
1421  PRINTFO("error in fragment tx, dropping subsequent fragments.\n");
1422  return 0;
1423  }
1424 
1425  /* set processed_ip_out_len to what we already sent from the IP payload*/
1426  processed_ip_out_len = packetbuf_payload_len + uncomp_hdr_len;
1427 
1428  /*
1429  * Create following fragments
1430  * Datagram tag is already in the buffer, we need to set the
1431  * FRAGN dispatch and for each fragment, the offset
1432  */
1433  packetbuf_hdr_len = SICSLOWPAN_FRAGN_HDR_LEN;
1434 /* PACKETBUF_FRAG_BUF->dispatch_size = */
1435 /* uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */
1436  SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1437  ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
1438  packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8;
1439  while(processed_ip_out_len < uip_len) {
1440  PRINTFO("sicslowpan output: fragment ");
1441  PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
1442 
1443  /* Copy payload and send */
1444  if(uip_len - processed_ip_out_len < packetbuf_payload_len) {
1445  /* last fragment */
1446  packetbuf_payload_len = uip_len - processed_ip_out_len;
1447  }
1448  PRINTFO("(offset %d, len %d, tag %d)\n",
1449  processed_ip_out_len >> 3, packetbuf_payload_len, frag_tag);
1450  memcpy(packetbuf_ptr + packetbuf_hdr_len,
1451  (uint8_t *)UIP_IP_BUF + processed_ip_out_len, packetbuf_payload_len);
1452  packetbuf_set_datalen(packetbuf_payload_len + packetbuf_hdr_len);
1453  q = queuebuf_new_from_packetbuf();
1454  if(q == NULL) {
1455  PRINTFO("could not allocate queuebuf, dropping fragment\n");
1456  return 0;
1457  }
1458  send_packet(&dest);
1459  queuebuf_to_packetbuf(q);
1460  queuebuf_free(q);
1461  q = NULL;
1462  processed_ip_out_len += packetbuf_payload_len;
1463 
1464  /* Check tx result. */
1465  if((last_tx_status == MAC_TX_COLLISION) ||
1466  (last_tx_status == MAC_TX_ERR) ||
1467  (last_tx_status == MAC_TX_ERR_FATAL)) {
1468  PRINTFO("error in fragment tx, dropping subsequent fragments.\n");
1469  return 0;
1470  }
1471  }
1472 #else /* SICSLOWPAN_CONF_FRAG */
1473  PRINTFO("sicslowpan output: Packet too large to be sent without fragmentation support; dropping packet\n");
1474  return 0;
1475 #endif /* SICSLOWPAN_CONF_FRAG */
1476  } else {
1477 
1478  /*
1479  * The packet does not need to be fragmented
1480  * copy "payload" and send
1481  */
1482  memcpy(packetbuf_ptr + packetbuf_hdr_len, (uint8_t *)UIP_IP_BUF + uncomp_hdr_len,
1484  packetbuf_set_datalen(uip_len - uncomp_hdr_len + packetbuf_hdr_len);
1485  send_packet(&dest);
1486  }
1487  return 1;
1488 }
1489 
1490 /*--------------------------------------------------------------------*/
1491 /** \brief Process a received 6lowpan packet.
1492  *
1493  * The 6lowpan packet is put in packetbuf by the MAC. If its a frag1 or
1494  * a non-fragmented packet we first uncompress the IP header. The
1495  * 6lowpan payload and possibly the uncompressed IP header are then
1496  * copied in siclowpan_buf. If the IP packet is complete it is copied
1497  * to uip_buf and the IP layer is called.
1498  *
1499  * \note We do not check for overlapping sicslowpan fragments
1500  * (it is a SHALL in the RFC 4944 and should never happen)
1501  */
1502 static void
1503 input(void)
1504 {
1505  /* size of the IP packet (read from fragment) */
1506  uint16_t frag_size = 0;
1507  /* offset of the fragment in the IP packet */
1508  uint8_t frag_offset = 0;
1509  uint8_t *buffer;
1510 
1511 #if SICSLOWPAN_CONF_FRAG
1512  uint8_t is_fragment = 0;
1513  int8_t frag_context = 0;
1514 
1515  /* tag of the fragment */
1516  uint16_t frag_tag = 0;
1517  uint8_t first_fragment = 0, last_fragment = 0;
1518 #endif /*SICSLOWPAN_CONF_FRAG*/
1519 
1520  /* Update link statistics */
1521  link_stats_input_callback(packetbuf_addr(PACKETBUF_ADDR_SENDER));
1522 
1523  /* init */
1524  uncomp_hdr_len = 0;
1525  packetbuf_hdr_len = 0;
1526 
1527  /* The MAC puts the 15.4 payload inside the packetbuf data buffer */
1529 
1530  /* This is default uip_buf since we assume that this is not fragmented */
1531  buffer = (uint8_t *)UIP_IP_BUF;
1532 
1533  /* Save the RSSI of the incoming packet in case the upper layer will
1534  want to query us for it later. */
1535  last_rssi = (signed short)packetbuf_attr(PACKETBUF_ATTR_RSSI);
1536 
1537 #if SICSLOWPAN_CONF_FRAG
1538 
1539  /*
1540  * Since we don't support the mesh and broadcast header, the first header
1541  * we look for is the fragmentation header
1542  */
1543  switch((GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0xf800) >> 8) {
1544  case SICSLOWPAN_DISPATCH_FRAG1:
1545  PRINTFI("sicslowpan input: FRAG1 ");
1546  frag_offset = 0;
1547 /* frag_size = (uip_ntohs(PACKETBUF_FRAG_BUF->dispatch_size) & 0x07ff); */
1548  frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1549 /* frag_tag = uip_ntohs(PACKETBUF_FRAG_BUF->tag); */
1550  frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1551  PRINTFI("size %d, tag %d, offset %d)\n",
1552  frag_size, frag_tag, frag_offset);
1553  packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
1554  /* printf("frag1 %d %d\n", reass_tag, frag_tag);*/
1555  first_fragment = 1;
1556  is_fragment = 1;
1557 
1558  /* Add the fragment to the fragmentation context */
1559  frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1560 
1561  if(frag_context == -1) {
1562  return;
1563  }
1564 
1565  buffer = frag_info[frag_context].first_frag;
1566 
1567  break;
1568  case SICSLOWPAN_DISPATCH_FRAGN:
1569  /*
1570  * set offset, tag, size
1571  * Offset is in units of 8 bytes
1572  */
1573  PRINTFI("sicslowpan input: FRAGN ");
1574  frag_offset = PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET];
1575  frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1576  frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1577  PRINTFI("size %d, tag %d, offset %d)\n",
1578  frag_size, frag_tag, frag_offset);
1579  packetbuf_hdr_len += SICSLOWPAN_FRAGN_HDR_LEN;
1580 
1581  /* If this is the last fragment, we may shave off any extrenous
1582  bytes at the end. We must be liberal in what we accept. */
1583  PRINTFI("last_fragment?: packetbuf_payload_len %d frag_size %d\n",
1584  packetbuf_datalen() - packetbuf_hdr_len, frag_size);
1585 
1586  /* Add the fragment to the fragmentation context (this will also
1587  copy the payload) */
1588  frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1589 
1590  if(frag_context == -1) {
1591  return;
1592  }
1593 
1594  /* Ok - add_fragment will store the fragment automatically - so
1595  we should not store more */
1596  buffer = NULL;
1597 
1598  if(frag_info[frag_context].reassembled_len >= frag_size) {
1599  last_fragment = 1;
1600  }
1601  is_fragment = 1;
1602  break;
1603  default:
1604  break;
1605  }
1606 
1607  if(is_fragment && !first_fragment) {
1608  /* this is a FRAGN, skip the header compression dispatch section */
1609  goto copypayload;
1610  }
1611 #endif /* SICSLOWPAN_CONF_FRAG */
1612 
1613  /* Process next dispatch and headers */
1614 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
1615  if((PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH] & 0xe0) == SICSLOWPAN_DISPATCH_IPHC) {
1616  PRINTFI("sicslowpan input: IPHC\n");
1617  uncompress_hdr_iphc(buffer, frag_size);
1618  } else
1619 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
1620  switch(PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH]) {
1621  case SICSLOWPAN_DISPATCH_IPV6:
1622  PRINTFI("sicslowpan input: IPV6\n");
1623  packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
1624 
1625  /* Put uncompressed IP header in sicslowpan_buf. */
1626  memcpy(buffer, packetbuf_ptr + packetbuf_hdr_len, UIP_IPH_LEN);
1627 
1628  /* Update uncomp_hdr_len and packetbuf_hdr_len. */
1629  packetbuf_hdr_len += UIP_IPH_LEN;
1630  uncomp_hdr_len += UIP_IPH_LEN;
1631  break;
1632  default:
1633  /* unknown header */
1634  PRINTFI("sicslowpan input: unknown dispatch: %u\n",
1635  PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH]);
1636  return;
1637  }
1638 
1639 
1640 #if SICSLOWPAN_CONF_FRAG
1641  copypayload:
1642 #endif /*SICSLOWPAN_CONF_FRAG*/
1643  /*
1644  * copy "payload" from the packetbuf buffer to the sicslowpan_buf
1645  * if this is a first fragment or not fragmented packet,
1646  * we have already copied the compressed headers, uncomp_hdr_len
1647  * and packetbuf_hdr_len are non 0, frag_offset is.
1648  * If this is a subsequent fragment, this is the contrary.
1649  */
1651  PRINTF("SICSLOWPAN: packet dropped due to header > total packet\n");
1652  return;
1653  }
1655 
1656  /* Sanity-check size of incoming packet to avoid buffer overflow */
1657  {
1658  int req_size = UIP_LLH_LEN + uncomp_hdr_len + (uint16_t)(frag_offset << 3)
1660  if(req_size > sizeof(uip_buf)) {
1661  PRINTF(
1662  "SICSLOWPAN: packet dropped, minimum required IP_BUF size: %d+%d+%d+%d=%d (current size: %u)\n",
1663  UIP_LLH_LEN, uncomp_hdr_len, (uint16_t)(frag_offset << 3),
1664  packetbuf_payload_len, req_size, (unsigned)sizeof(uip_buf));
1665  return;
1666  }
1667  }
1668 
1669  /* copy the payload if buffer is non-null - which is only the case with first fragment
1670  or packets that are non fragmented */
1671  if(buffer != NULL) {
1672  memcpy((uint8_t *)buffer + uncomp_hdr_len, packetbuf_ptr + packetbuf_hdr_len, packetbuf_payload_len);
1673  }
1674 
1675  /* update processed_ip_in_len if fragment, sicslowpan_len otherwise */
1676 
1677 #if SICSLOWPAN_CONF_FRAG
1678  if(frag_size > 0) {
1679  /* Add the size of the header only for the first fragment. */
1680  if(first_fragment != 0) {
1681  frag_info[frag_context].reassembled_len = uncomp_hdr_len + packetbuf_payload_len;
1682  frag_info[frag_context].first_frag_len = uncomp_hdr_len + packetbuf_payload_len;
1683  }
1684  /* For the last fragment, we are OK if there is extrenous bytes at
1685  the end of the packet. */
1686  if(last_fragment != 0) {
1687  frag_info[frag_context].reassembled_len = frag_size;
1688  /* copy to uip */
1689  copy_frags2uip(frag_context);
1690  }
1691  }
1692 
1693  /*
1694  * If we have a full IP packet in sicslowpan_buf, deliver it to
1695  * the IP stack
1696  */
1697  if(!is_fragment || last_fragment) {
1698  /* packet is in uip already - just set length */
1699  if(is_fragment != 0 && last_fragment != 0) {
1700  uip_len = frag_size;
1701  } else {
1703  }
1704 #else
1706 #endif /* SICSLOWPAN_CONF_FRAG */
1707  PRINTFI("sicslowpan input: IP packet ready (length %d)\n",
1708  uip_len);
1709 
1710 #if DEBUG
1711  {
1712  uint16_t ndx;
1713  PRINTF("after decompression %u:", UIP_IP_BUF->len[1]);
1714  for (ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
1715  uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
1716  PRINTF("%02x", data);
1717  }
1718  PRINTF("\n");
1719  }
1720 #endif
1721 
1722  /* if callback is set then set attributes and call */
1723  if(callback) {
1724  set_packet_attrs();
1725  callback->input_callback();
1726  }
1727 
1728  tcpip_input();
1729 #if SICSLOWPAN_CONF_FRAG
1730  }
1731 #endif /* SICSLOWPAN_CONF_FRAG */
1732 }
1733 /** @} */
1734 
1735 /*--------------------------------------------------------------------*/
1736 /* \brief 6lowpan init function (called by the MAC layer) */
1737 /*--------------------------------------------------------------------*/
1738 void
1739 sicslowpan_init(void)
1740 {
1741  /*
1742  * Set out output function as the function to be called from uIP to
1743  * send a packet.
1744  */
1745 
1746  tcpip_set_outputfunc(output);
1747 
1748 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
1749 /* Preinitialize any address contexts for better header compression
1750  * (Saves up to 13 bytes per 6lowpan packet)
1751  * The platform contiki-conf.h file can override this using e.g.
1752  * #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xbb;addr_contexts[0].prefix[1]=0xbb;}
1753  */
1754 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
1755  addr_contexts[0].used = 1;
1756  addr_contexts[0].number = 0;
1757 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0
1758  SICSLOWPAN_CONF_ADDR_CONTEXT_0;
1759 #else
1760  addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0;
1761  addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1;
1762 #endif
1763 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
1764 
1765 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1
1766  {
1767  int i;
1768  for(i = 1; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
1769 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1
1770  if (i==1) {
1771  addr_contexts[1].used = 1;
1772  addr_contexts[1].number = 1;
1773  SICSLOWPAN_CONF_ADDR_CONTEXT_1;
1774 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
1775  } else if (i==2) {
1776  addr_contexts[2].used = 1;
1777  addr_contexts[2].number = 2;
1778  SICSLOWPAN_CONF_ADDR_CONTEXT_2;
1779 #endif
1780  } else {
1781  addr_contexts[i].used = 0;
1782  }
1783 #else
1784  addr_contexts[i].used = 0;
1785 #endif /* SICSLOWPAN_CONF_ADDR_CONTEXT_1 */
1786  }
1787  }
1788 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */
1789 
1790 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
1791 }
1792 /*--------------------------------------------------------------------*/
1793 int
1794 sicslowpan_get_last_rssi(void)
1795 {
1796  return last_rssi;
1797 }
1798 /*--------------------------------------------------------------------*/
1799 const struct network_driver sicslowpan_driver = {
1800  "sicslowpan",
1801  sicslowpan_init,
1802  input
1803 };
1804 /*--------------------------------------------------------------------*/
1805 /** @} */
1806 
void uip_log(char *msg)
Print out a uIP log message.
Definition: uip-log.c:3
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:158
uip_len
The length of the packet in the uip_buf buffer.
Definition: tcp_loader.c:75
static uint8_t * hc06_ptr
pointer to the byte where to write next inline field.
Definition: sicslowpan.c:504
static void send_packet(linkaddr_t *dest)
This function is called by the 6lowpan code to send out a packet.
Definition: sicslowpan.c:1243
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:129
static uint8_t * packetbuf_ptr
A pointer to the packetbuf buffer.
Definition: sicslowpan.c:184
The MAC layer did not get an acknowledgement for the packet.
Definition: mac.h:83
Header file for IPv6-related data structures.
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:76
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1239
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1503
#define UIP_LLH_LEN
The link level header length.
Definition: uipopt.h:160
A timer.
Definition: timer.h:86
The header for fragments.
Definition: sicslowpan.h:222
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
Definition: uip.h:1978
const linkaddr_t linkaddr_null
The null Rime address.
Definition: eth-conf.c:37
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:523
static void compress_hdr_iphc(linkaddr_t *link_destaddr)
Compress IP/UDP header.
Definition: sicslowpan.c:669
#define UIP_IP_BUF
Pointer to IP header.
Definition: uip-nd6.c:104
static uint8_t packetbuf_hdr_len
packetbuf_hdr_len is the total length of (the processed) 6lowpan headers (fragment headers...
Definition: sicslowpan.c:191
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 3513 a is of type uip_ipaddr_t*
Definition: uip.h:2103
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:956
#define SICSLOWPAN_FIXED_HDRLEN
Fixed size of a frame header.
Definition: sicslowpan.c:172
#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS
If we use IPHC compression, how many address contexts do we support.
Definition: uipopt.h:584
The MAC layer transmission could not be performed because of a fatal error.
Definition: mac.h:93
static struct sicslowpan_addr_context * context
Addresses contexts for IPHC.
Definition: sicslowpan.c:501
static void packet_sent(void *ptr, int status, int transmissions)
Callback function for the MAC packet sent callback.
Definition: sicslowpan.c:1227
#define MAC_MAX_PAYLOAD
Maximum available size for frame headers, link layer security-related overhead, as well as 6LoWPAN pa...
Definition: sicslowpan.c:155
Header for the Contiki/uIP interface.
Header file for the Rime stack
The MAC layer transmission was OK.
Definition: mac.h:79
#define NULL
The null pointer.
802.3 address
Definition: uip.h:129
static struct sicslowpan_addr_context * addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr)
find the context corresponding to prefix ipaddr
Definition: sicslowpan.c:541
#define SICSLOWPAN_REASS_MAXAGE
Timeout for packet reassembly at the 6lowpan layer (should be < 60s)
Definition: uipopt.h:570
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
#define UIP_ICMP_BUF
Pointer to ICMP header.
Definition: uip-nd6.c:105
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
static volatile clock_time_t count
These routines define the AVR-specific calls declared in /core/sys/clock.h CLOCK_SECOND is the number...
Definition: clock.c:80
Header file for the uIP TCP/IP stack.
static int last_tx_status
the result of the last transmitted fragment
Definition: sicslowpan.c:210
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:151
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:170
A set of debugging macros for the IP stack
static uint8_t output(const uip_lladdr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
Definition: sicslowpan.c:1275
static int packetbuf_payload_len
The length of the payload in the Packetbuf buffer.
Definition: sicslowpan.c:199
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip.c:118
#define sicslowpan_is_iid_16_bit_compressable(a)
check whether we can compress the IID in address 'a' to 16 bits.
Definition: sicslowpan.h:240
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two Rime addresses.
Definition: linkaddr.c:66
#define COMPRESSION_THRESHOLD
Some MAC layers need a minimum payload, which is configurable through the SICSLOWPAN_CONF_COMPRESSION...
Definition: sicslowpan.c:164
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
Definition: uip.h:2019
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
Definition: linkaddr.c:60
The structure of a network driver in Contiki.
Definition: netstack.h:117
void tcpip_input(void)
Deliver an incoming packet to the TCP/IP stack.
Definition: tcpip.c:522
#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:2087
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:205
static struct sicslowpan_addr_context * addr_context_lookup_by_number(uint8_t number)
find the context with the given number
Definition: sicslowpan.c:558
Header file for the 6lowpan implementation (RFC4944 and draft-hui-6lowpan-hc-01) ...
Include file for the Contiki low-layer network stack (NETSTACK)
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:542
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:122