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