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