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