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