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