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