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