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 uncomp_hdr_len = UIP_IPH_LEN;
913
914 /* Start of ext hdr compression or UDP compression */
915 /* pick out the next-header position */
916 next_hdr = &UIP_IP_BUF->proto;
917 next_nhc = iphc_ptr; /* here we set the next header is compressed. */
918 ext_hdr_len = 0;
919 /* reserve the write place of this next header position */
920 LOG_DBG("compression: first header: %d\n", *next_hdr);
921 while(next_hdr != NULL && IS_COMPRESSABLE_PROTO(*next_hdr)) {
922 LOG_DBG("compression: next header: %d\n", *next_hdr);
923 int proto = -1; /* used for the specific ext hdr */
924 /* UDP and EXT header compression */
925 switch(*next_hdr) {
926 case UIP_PROTO_HBHO:
927 proto = SICSLOWPAN_NHC_ETX_HDR_HBHO;
928 case UIP_PROTO_ROUTING:
929 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_ROUTING : proto;
930 case UIP_PROTO_FRAG:
931 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_FRAG : proto;
932 case UIP_PROTO_DESTO:
933 /* Handle the header here! */
934 {
935 struct uip_ext_hdr *ext_hdr =
936 (struct uip_ext_hdr *) UIP_IPPAYLOAD_BUF_POS(ext_hdr_len);
937 int len;
938 proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_DESTO : proto;
939 /* Len is defined to be in octets from the length byte */
940 len = (ext_hdr->len << 3) + 8;
941 LOG_DBG("compression: next header %d (len:%d)\n", *next_hdr, len);
942 /* pick up the next header */
943 next_hdr = &ext_hdr->next;
944 /* If the next header is not compressable we need to reserve the
945 NHC byte extra - before the next header here. This is due to
946 next not being elided in that case. */
947 if(!IS_COMPRESSABLE_PROTO(*next_hdr)) {
948 CHECK_BUFFER_SPACE(1);
949 iphc_ptr++;
950 LOG_DBG("compression: keeping the next header in this ext hdr: %d\n",
951 ext_hdr->next);
952 }
953 /* copy the ext-hdr into the hc06 buffer */
954 CHECK_BUFFER_SPACE(len);
955 memcpy(iphc_ptr, ext_hdr, len);
956 /* modify the len to octets */
957 ext_hdr = (struct uip_ext_hdr *) iphc_ptr;
958 ext_hdr->len = len - 2; /* Len should be in bytes from len byte*/
959 ext_hdr_len += len;
960 iphc_ptr += len;
961 uncomp_hdr_len += len;
962
963 /* Write this next header - with its NHC header - including flag
964 to tell if next header is elided in this one also- */
965 *next_nhc = SICSLOWPAN_NHC_EXT_HDR |
966 (IS_COMPRESSABLE_PROTO(*next_hdr) ? SICSLOWPAN_NHC_BIT : 0) |
967 (proto << 1);
968 /* update the position of the next header */
969 next_nhc = iphc_ptr;
970 }
971 break;
972 case UIP_PROTO_UDP:
973 /* allocate a byte for the next header posision as UDP has no next */
974 iphc_ptr++;
975 udp_buf = UIP_UDP_BUF_POS(ext_hdr_len);
976 LOG_DBG("compression: inlined UDP ports on send side: %x, %x\n",
977 UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
978 /* Mask out the last 4 bits can be used as a mask */
979 if(((UIP_HTONS(udp_buf->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
980 ((UIP_HTONS(udp_buf->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
981 /* we can compress 12 bits of both source and dest */
982 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_11;
983 LOG_DBG("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
984 CHECK_BUFFER_SPACE(1);
985 *iphc_ptr =
986 (uint8_t)((UIP_HTONS(udp_buf->srcport) -
987 SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
988 (uint8_t)((UIP_HTONS(udp_buf->destport) -
989 SICSLOWPAN_UDP_4_BIT_PORT_MIN));
990 iphc_ptr += 1;
991 } else if((UIP_HTONS(udp_buf->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
992 /* we can compress 8 bits of dest, leave source. */
993 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_01;
994 LOG_DBG("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
995 CHECK_BUFFER_SPACE(3);
996 memcpy(iphc_ptr, &udp_buf->srcport, 2);
997 *(iphc_ptr + 2) =
998 (uint8_t)((UIP_HTONS(udp_buf->destport) -
999 SICSLOWPAN_UDP_8_BIT_PORT_MIN));
1000 iphc_ptr += 3;
1001 } else if((UIP_HTONS(udp_buf->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
1002 /* we can compress 8 bits of src, leave dest. Copy compressed port */
1003 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_10;
1004 LOG_DBG("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *next_nhc);
1005 CHECK_BUFFER_SPACE(3);
1006 *iphc_ptr =
1007 (uint8_t)((UIP_HTONS(udp_buf->srcport) -
1008 SICSLOWPAN_UDP_8_BIT_PORT_MIN));
1009 memcpy(iphc_ptr + 1, &udp_buf->destport, 2);
1010 iphc_ptr += 3;
1011 } else {
1012 /* we cannot compress. Copy uncompressed ports, full checksum */
1013 *next_nhc = SICSLOWPAN_NHC_UDP_CS_P_00;
1014 LOG_DBG("IPHC: cannot compress UDP headers\n");
1015 CHECK_BUFFER_SPACE(4);
1016 memcpy(iphc_ptr, &udp_buf->srcport, 4);
1017 iphc_ptr += 4;
1018 }
1019 /* always inline the checksum */
1020 CHECK_BUFFER_SPACE(2);
1021 memcpy(iphc_ptr, &udp_buf->udpchksum, 2);
1022 iphc_ptr += 2;
1023 uncomp_hdr_len += UIP_UDPH_LEN;
1024 /* this is the final header. */
1025 next_hdr = NULL;
1026 break;
1027 default:
1028 LOG_ERR("compression: could not handle compression of header");
1029 }
1030 }
1031 if(next_hdr != NULL) {
1032 /* Last header could not be compressed - we assume that this is then OK!*/
1033 /* as the last EXT_HDR should be "uncompressed" and have the next there */
1034 LOG_DBG("compression: last header could is not compressed: %d\n", *next_hdr);
1035 }
1036 /* before the packetbuf_hdr_len operation */
1037 PACKETBUF_IPHC_BUF[0] = iphc0;
1038 PACKETBUF_IPHC_BUF[1] = iphc1;
1039
1040 if(LOG_DBG_ENABLED) {
1041 uint16_t ndx;
1042 LOG_DBG("compression: after (%d): ", (int)(iphc_ptr - packetbuf_ptr));
1043 for(ndx = 0; ndx < iphc_ptr - packetbuf_ptr; ndx++) {
1044 uint8_t data = ((uint8_t *) packetbuf_ptr)[ndx];
1045 LOG_DBG_("%02x", data);
1046 }
1047 LOG_DBG_("\n");
1048 }
1049
1051
1052 return 1;
1053}
1054
1055/*--------------------------------------------------------------------*/
1056/**
1057 * \brief Uncompress IPHC (i.e., IPHC and LOWPAN_UDP) headers and put
1058 * them in sicslowpan_buf
1059 *
1060 * This function is called by the input function when the dispatch is
1061 * IPHC.
1062 * We %process the packet in the packetbuf buffer, uncompress the header
1063 * fields, and copy the result in the sicslowpan buffer.
1064 * At the end of the decompression, packetbuf_hdr_len and uncompressed_hdr_len
1065 * are set to the appropriate values
1066 *
1067 * \param buf Pointer to the buffer to uncompress the packet into.
1068 * \param buf_size The size of the buffer to uncompress the packet into.
1069 * \param ip_len Equal to 0 if the packet is not a fragment (IP length
1070 * is then inferred from the L2 length), non 0 if the packet is a 1st
1071 * fragment.
1072 * \return A boolean value indicating whether the uncompression succeeded.
1073 */
1074static bool
1075uncompress_hdr_iphc(uint8_t *buf, uint16_t buf_size, uint16_t ip_len)
1076{
1077 uint8_t tmp, iphc0, iphc1, nhc;
1078 struct uip_ext_hdr *exthdr;
1079 uint8_t* last_nextheader;
1080 uint8_t* ip_payload;
1081 uint8_t ext_hdr_len = 0;
1082 uint16_t cmpr_len;
1083
1084/* Macro used only internally, during header uncompression. Checks if there
1085 * is sufficient space in packetbuf before reading any further. */
1086#define CHECK_READ_SPACE(readlen) \
1087 if((iphc_ptr - packetbuf_ptr) + (readlen) > cmpr_len) { \
1088 LOG_WARN("Not enough packetbuf space to decompress header (%u bytes, %u left). Aborting.\n", \
1089 (unsigned)(readlen), (unsigned)(cmpr_len - (iphc_ptr - packetbuf_ptr))); \
1090 return false; \
1091 }
1092
1093 /* at least two byte will be used for the encoding */
1094 cmpr_len = packetbuf_datalen();
1095 if(cmpr_len < packetbuf_hdr_len + 2) {
1096 return false;
1097 }
1099
1100 iphc0 = PACKETBUF_IPHC_BUF[0];
1101 iphc1 = PACKETBUF_IPHC_BUF[1];
1102
1103 /* another if the CID flag is set */
1104 if(iphc1 & SICSLOWPAN_IPHC_CID) {
1105 LOG_DBG("uncompression: CID flag set - increase header with one\n");
1106 iphc_ptr++;
1107 }
1108
1109 /* Traffic class and flow label */
1110 if((iphc0 & SICSLOWPAN_IPHC_FL_C) == 0) {
1111 /* Flow label are carried inline */
1112 if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1113 /* Traffic class is carried inline */
1114 CHECK_READ_SPACE(4);
1115 memcpy(&SICSLOWPAN_IP_BUF(buf)->tcflow, iphc_ptr + 1, 3);
1116 tmp = *iphc_ptr;
1117 iphc_ptr += 4;
1118 /* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
1119 /* set version, pick highest DSCP bits and set in vtc */
1120 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((tmp >> 2) & 0x0f);
1121 /* ECN rolled down two steps + lowest DSCP bits at top two bits */
1122 SICSLOWPAN_IP_BUF(buf)->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
1123 (SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f);
1124 } else {
1125 /* Traffic class is compressed (set version and no TC)*/
1126 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1127 /* highest flow label bits + ECN bits */
1128 CHECK_READ_SPACE(3);
1129 SICSLOWPAN_IP_BUF(buf)->tcflow = (*iphc_ptr & 0x0F) |
1130 ((*iphc_ptr >> 2) & 0x30);
1131 memcpy(&SICSLOWPAN_IP_BUF(buf)->flow, iphc_ptr + 1, 2);
1132 iphc_ptr += 3;
1133 }
1134 } else {
1135 /* Version is always 6! */
1136 /* Version and flow label are compressed */
1137 if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
1138 /* Traffic class is inline */
1139 CHECK_READ_SPACE(1);
1140 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*iphc_ptr >> 2) & 0x0f);
1141 SICSLOWPAN_IP_BUF(buf)->tcflow = ((*iphc_ptr << 6) & 0xC0) | ((*iphc_ptr >> 2) & 0x30);
1142 SICSLOWPAN_IP_BUF(buf)->flow = 0;
1143 iphc_ptr += 1;
1144 } else {
1145 /* Traffic class is compressed */
1146 SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
1147 SICSLOWPAN_IP_BUF(buf)->tcflow = 0;
1148 SICSLOWPAN_IP_BUF(buf)->flow = 0;
1149 }
1150 }
1151
1152 /* Next Header */
1153 if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
1154 /* Next header is carried inline */
1155 CHECK_READ_SPACE(1);
1156 SICSLOWPAN_IP_BUF(buf)->proto = *iphc_ptr;
1157 LOG_DBG("uncompression: next header inline: %d\n", SICSLOWPAN_IP_BUF(buf)->proto);
1158 iphc_ptr += 1;
1159 }
1160
1161 /* Hop limit */
1162 if((iphc0 & 0x03) != SICSLOWPAN_IPHC_TTL_I) {
1163 SICSLOWPAN_IP_BUF(buf)->ttl = ttl_values[iphc0 & 0x03];
1164 } else {
1165 CHECK_READ_SPACE(1);
1166 SICSLOWPAN_IP_BUF(buf)->ttl = *iphc_ptr;
1167 iphc_ptr += 1;
1168 }
1169
1170 /* put the source address compression mode SAM in the tmp var */
1171 tmp = ((iphc1 & SICSLOWPAN_IPHC_SAM_11) >> SICSLOWPAN_IPHC_SAM_BIT) & 0x03;
1172
1173 /* context based compression */
1174 if(iphc1 & SICSLOWPAN_IPHC_SAC) {
1175 uint8_t sci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
1176 PACKETBUF_IPHC_BUF[2] >> 4 : 0;
1177
1178 /* Source address - check context != NULL only if SAM bits are != 0*/
1179 struct sicslowpan_addr_context *source_context;
1180 if (tmp != 0) {
1181 source_context = addr_context_lookup_by_number(sci);
1182 if(!source_context) {
1183 LOG_ERR("uncompression: error source context not found\n");
1184 return false;
1185 }
1186 } else {
1187 source_context = NULL;
1188 }
1189 /* if tmp == 0 we do not have a context and therefore no prefix */
1190 if(!uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr,
1191 source_context ? source_context->prefix : NULL,
1192 unc_ctxconf[tmp],
1193 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
1194 return false;
1195 }
1196 } else {
1197 /* no compression and link local */
1198 if(!uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr, llprefix,
1199 unc_llconf[tmp],
1200 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
1201 return false;
1202 }
1203 }
1204
1205 /* Destination address */
1206 /* put the destination address compression mode into tmp */
1207 tmp = ((iphc1 & SICSLOWPAN_IPHC_DAM_11) >> SICSLOWPAN_IPHC_DAM_BIT) & 0x03;
1208
1209 /* multicast compression */
1210 if(iphc1 & SICSLOWPAN_IPHC_M) {
1211 /* context based multicast compression */
1212 if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1213 /* TODO: implement this */
1214 } else {
1215 /* non-context based multicast compression - */
1216 /* DAM_00: 128 bits */
1217 /* DAM_01: 48 bits FFXX::00XX:XXXX:XXXX */
1218 /* DAM_10: 32 bits FFXX::00XX:XXXX */
1219 /* DAM_11: 8 bits FF02::00XX */
1220 uint8_t prefix[] = {0xff, 0x02};
1221 if(tmp > 0 && tmp < 3) {
1222 CHECK_READ_SPACE(1);
1223 prefix[1] = *iphc_ptr;
1224 iphc_ptr++;
1225 }
1226
1227 if(!uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, prefix,
1228 unc_mxconf[tmp], NULL)) {
1229 return false;
1230 }
1231 }
1232 } else {
1233 /* no multicast */
1234 /* Context based */
1235 if(iphc1 & SICSLOWPAN_IPHC_DAC) {
1236 uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
1237 struct sicslowpan_addr_context *destination_context =
1239
1240 /* all valid cases below need the context! */
1241 if(!destination_context) {
1242 LOG_ERR("uncompression: error destination context not found\n");
1243 return false;
1244 }
1245 if(!uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr,
1246 destination_context->prefix,
1247 unc_ctxconf[tmp],
1248 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
1249 return false;
1250 }
1251 } else {
1252 /* not context based => link local M = 0, DAC = 0 - same as SAC */
1253 if(!uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, llprefix,
1254 unc_llconf[tmp],
1255 (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
1256 return false;
1257 }
1258 }
1259 }
1260 uncomp_hdr_len += UIP_IPH_LEN;
1261
1262 /* Next header processing - continued */
1263 nhc = iphc0 & SICSLOWPAN_IPHC_NH_C;
1264 /* The next header is compressed, NHC is following */
1265 last_nextheader = &SICSLOWPAN_IP_BUF(buf)->proto;
1266 ip_payload = SICSLOWPAN_IPPAYLOAD_BUF(buf);
1267
1268 CHECK_READ_SPACE(1);
1269 while(nhc && (*iphc_ptr & SICSLOWPAN_NHC_MASK) == SICSLOWPAN_NHC_EXT_HDR) {
1270 uint8_t eid = (*iphc_ptr & 0x0e) >> 1;
1271 /* next header compression flag */
1272 uint8_t nh = (*iphc_ptr & 0x01);
1273 uint8_t next = 0;
1274 uint8_t len;
1275 uint8_t proto;
1276
1277 nhc = nh;
1278
1279 iphc_ptr++;
1280 CHECK_READ_SPACE(1);
1281 if(!nh) {
1282 next = *iphc_ptr;
1283 iphc_ptr++;
1284 LOG_DBG("uncompression: next header is inlined. Next: %d\n", next);
1285 }
1286 CHECK_READ_SPACE(1);
1287 len = *iphc_ptr;
1288 iphc_ptr++;
1289
1290 LOG_DBG("uncompression: found ext header id: %d next: %d len: %d\n", eid, next, len);
1291 switch(eid) {
1292 case SICSLOWPAN_NHC_ETX_HDR_HBHO:
1293 proto = UIP_PROTO_HBHO;
1294 break;
1295 case SICSLOWPAN_NHC_ETX_HDR_ROUTING:
1296 proto = UIP_PROTO_ROUTING;
1297 break;
1298 case SICSLOWPAN_NHC_ETX_HDR_FRAG:
1299 proto = UIP_PROTO_FRAG;
1300 break;
1301 case SICSLOWPAN_NHC_ETX_HDR_DESTO:
1302 proto = UIP_PROTO_DESTO;
1303 break;
1304 default:
1305 LOG_DBG("uncompression: error unsupported ext header\n");
1306 return false;
1307 }
1308 *last_nextheader = proto;
1309
1310 /* Check that there is enough room to write the extension header. */
1311 if((ip_payload - buf) + UIP_EXT_HDR_LEN + len > buf_size) {
1312 LOG_WARN("uncompression: cannot write ext header beyond target buffer\n");
1313 return false;
1314 }
1315
1316 /* uncompress the extension header */
1317 exthdr = (struct uip_ext_hdr *)ip_payload;
1318 exthdr->len = (UIP_EXT_HDR_LEN + len) / 8;
1319 if(exthdr->len == 0) {
1320 LOG_WARN("Extension header length is below 8\n");
1321 return false;
1322 }
1323 exthdr->len--;
1324 exthdr->next = next;
1325 last_nextheader = &exthdr->next;
1326
1327 /* The loop condition needs to read one byte after the next len bytes in the buffer. */
1328 CHECK_READ_SPACE(len + 1);
1329 memcpy((uint8_t *)exthdr + UIP_EXT_HDR_LEN, iphc_ptr, len);
1330 iphc_ptr += len;
1331
1332 uncomp_hdr_len += (exthdr->len + 1) * 8;
1333 ip_payload += (exthdr->len + 1) * 8;
1334 ext_hdr_len += (exthdr->len + 1) * 8;
1335
1336 LOG_DBG("uncompression: %d len: %d exthdr len: %d (calc: %d)\n",
1337 proto, len, exthdr->len, (exthdr->len + 1) * 8);
1338 }
1339
1340 /* The next header is compressed, NHC is following */
1341 CHECK_READ_SPACE(1);
1342 if(nhc && (*iphc_ptr & SICSLOWPAN_NHC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) {
1343 struct uip_udp_hdr *udp_buf;
1344 uint16_t udp_len;
1345 uint8_t checksum_compressed;
1346
1347 /* Check that there is enough room to write the UDP header. */
1348 if((ip_payload - buf) + UIP_UDPH_LEN > buf_size) {
1349 LOG_WARN("uncompression: cannot write UDP header beyond target buffer\n");
1350 return false;
1351 }
1352
1353 udp_buf = (struct uip_udp_hdr *)ip_payload;
1354 *last_nextheader = UIP_PROTO_UDP;
1355 checksum_compressed = *iphc_ptr & SICSLOWPAN_NHC_UDP_CHECKSUMC;
1356 LOG_DBG("uncompression: incoming header value: %i\n", *iphc_ptr);
1357 switch(*iphc_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
1358 case SICSLOWPAN_NHC_UDP_CS_P_00:
1359 /* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
1360 CHECK_READ_SPACE(5);
1361 memcpy(&udp_buf->srcport, iphc_ptr + 1, 2);
1362 memcpy(&udp_buf->destport, iphc_ptr + 3, 2);
1363 LOG_DBG("uncompression: UDP ports (ptr+5): %x, %x\n",
1364 UIP_HTONS(udp_buf->srcport),
1365 UIP_HTONS(udp_buf->destport));
1366 iphc_ptr += 5;
1367 break;
1368
1369 case SICSLOWPAN_NHC_UDP_CS_P_01:
1370 /* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
1371 LOG_DBG("uncompression: destination address\n");
1372 CHECK_READ_SPACE(4);
1373 memcpy(&udp_buf->srcport, iphc_ptr + 1, 2);
1374 udp_buf->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(iphc_ptr + 3)));
1375 LOG_DBG("uncompression: UDP ports (ptr+4): %x, %x\n",
1376 UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1377 iphc_ptr += 4;
1378 break;
1379
1380 case SICSLOWPAN_NHC_UDP_CS_P_10:
1381 /* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit inline*/
1382 LOG_DBG("uncompression: source address\n");
1383 CHECK_READ_SPACE(4);
1384 udp_buf->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
1385 (*(iphc_ptr + 1)));
1386 memcpy(&udp_buf->destport, iphc_ptr + 2, 2);
1387 LOG_DBG("uncompression: UDP ports (ptr+4): %x, %x\n",
1388 UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1389 iphc_ptr += 4;
1390 break;
1391
1392 case SICSLOWPAN_NHC_UDP_CS_P_11:
1393 /* 1 byte for NHC, 1 byte for ports */
1394 CHECK_READ_SPACE(2);
1395 udp_buf->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1396 (*(iphc_ptr + 1) >> 4));
1397 udp_buf->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
1398 ((*(iphc_ptr + 1)) & 0x0F));
1399 LOG_DBG("uncompression: UDP ports (ptr+2): %x, %x\n",
1400 UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
1401
1402 iphc_ptr += 2;
1403 break;
1404 default:
1405 LOG_DBG("uncompression: error unsupported UDP compression\n");
1406 return false;
1407 }
1408 if(!checksum_compressed) { /* has_checksum, default */
1409 CHECK_READ_SPACE(2);
1410 memcpy(&udp_buf->udpchksum, iphc_ptr, 2);
1411 iphc_ptr += 2;
1412 LOG_DBG("uncompression: checksum included\n");
1413 } else {
1414 LOG_DBG("uncompression: checksum *NOT* included\n");
1415 }
1416
1417 /* length field in UDP header (8 byte header + payload) */
1418 udp_len = 8 + packetbuf_datalen() - (iphc_ptr - packetbuf_ptr);
1419 udp_buf->udplen = UIP_HTONS(ip_len == 0 ? udp_len :
1420 ip_len - UIP_IPH_LEN - ext_hdr_len);
1421 LOG_DBG("uncompression: UDP length: %u (ext: %u) ip_len: %d udp_len: %d\n",
1422 UIP_HTONS(udp_buf->udplen), ext_hdr_len, ip_len, udp_len);
1423
1424 uncomp_hdr_len += UIP_UDPH_LEN;
1425 }
1426
1428
1429 /* IP length field. */
1430 if(ip_len == 0) {
1431 int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
1432 LOG_DBG("uncompression: IP payload length: %d. %u - %u + %u - %u\n", len,
1434
1435 /* This is not a fragmented packet */
1436 SICSLOWPAN_IP_BUF(buf)->len[0] = len >> 8;
1437 SICSLOWPAN_IP_BUF(buf)->len[1] = len & 0x00FF;
1438 } else {
1439 /* This is a 1st fragment */
1440 SICSLOWPAN_IP_BUF(buf)->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
1441 SICSLOWPAN_IP_BUF(buf)->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
1442 }
1443
1444 return true;
1445}
1446/** @} */
1447#endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
1448
1449#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH
1450/*--------------------------------------------------------------------*/
1451/**
1452 * \brief Adds Paging dispatch byte
1453 */
1454static void
1456{
1457 /* Add paging dispatch to Page 1 */
1458 PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] = SICSLOWPAN_DISPATCH_PAGING | (page & 0x0f);
1460}
1461/*--------------------------------------------------------------------*/
1462/**
1463 * \brief Adds 6lorh headers before IPHC
1464 */
1465static void
1467{
1468 /* 6LoRH is not implemented yet */
1469}
1470#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */
1471
1472/*--------------------------------------------------------------------*/
1473/**
1474 * \brief Digest 6lorh headers before IPHC
1475 */
1476static void
1478{
1479 /* Is this a paging dispatch? */
1480 if((PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_PAGING_MASK) == SICSLOWPAN_DISPATCH_PAGING) {
1481 /* Parse page number */
1482 curr_page = PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & 0x0f;
1484 }
1485}
1486/*--------------------------------------------------------------------*/
1487/**
1488 * \brief Digest 6lorh headers before IPHC
1489 */
1490static void
1492{
1493 /* 6LoRH is not implemented yet */
1494}
1495/*--------------------------------------------------------------------*/
1496/** \name IPv6 dispatch "compression" function
1497 * @{ */
1498/*--------------------------------------------------------------------*/
1499/* \brief Packets "Compression" when only IPv6 dispatch is used
1500 *
1501 * There is no compression in this case, all fields are sent
1502 * inline. We just add the IPv6 dispatch byte before the packet.
1503 * \verbatim
1504 * 0 1 2 3
1505 * 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
1506 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1507 * | IPv6 Dsp | IPv6 header and payload ...
1508 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1509 * \endverbatim
1510 */
1511#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
1512static void
1513compress_hdr_ipv6(void)
1514{
1515 *packetbuf_ptr = SICSLOWPAN_DISPATCH_IPV6;
1516 packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
1517 memcpy(packetbuf_ptr + packetbuf_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
1518 packetbuf_hdr_len += UIP_IPH_LEN;
1519 uncomp_hdr_len += UIP_IPH_LEN;
1520 return;
1521}
1522#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
1523/** @} */
1524
1525/*--------------------------------------------------------------------*/
1526/** \name Input/output functions common to all compression schemes
1527 * @{ */
1528/*--------------------------------------------------------------------*/
1529/**
1530 * Callback function for the MAC packet sent callback
1531 */
1532static void
1533packet_sent(void *ptr, int status, int transmissions)
1534{
1535 const linkaddr_t *dest;
1536
1537 if(callback != NULL) {
1538 callback->output_callback(status);
1539 }
1540 last_tx_status = status;
1541
1542 /* What follows only applies to unicast */
1543 dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
1544 if(linkaddr_cmp(dest, &linkaddr_null)) {
1545 return;
1546 }
1547
1548 /* Update neighbor link statistics */
1549 link_stats_packet_sent(dest, status, transmissions);
1550
1551 /* Call routing protocol link callback */
1552 NETSTACK_ROUTING.link_callback(dest, status, transmissions);
1553
1554 /* DS6 callback, used for UIP_DS6_LL_NUD */
1555 uip_ds6_link_callback(status, transmissions);
1556}
1557/*--------------------------------------------------------------------*/
1558/**
1559 * \brief This function is called by the 6lowpan code to send out a
1560 * packet.
1561 */
1562static void
1564{
1565 /* Provide a callback function to receive the result of
1566 a packet transmission. */
1567 NETSTACK_MAC.send(&packet_sent, NULL);
1568
1569 /* If we are sending multiple packets in a row, we need to let the
1570 watchdog know that we are still alive. */
1572}
1573#if SICSLOWPAN_CONF_FRAG
1574/*--------------------------------------------------------------------*/
1575/**
1576 * \brief This function is called by the 6lowpan code to copy a fragment's
1577 * payload from uIP and send it down the stack.
1578 * \param uip_offset the offset in the uIP buffer where to copy the payload from
1579 * \param dest the link layer destination address of the packet
1580 * \return 1 if success, 0 otherwise
1581 */
1582static int
1583fragment_copy_payload_and_send(uint16_t uip_offset)
1584{
1585 struct queuebuf *q;
1586
1587 /* Now copy fragment payload from uip_buf */
1589 (uint8_t *)UIP_IP_BUF + uip_offset, packetbuf_payload_len);
1591
1592 /* Backup packetbuf to queuebuf. Enables preserving attributes for all framgnets */
1593 q = queuebuf_new_from_packetbuf();
1594 if(q == NULL) {
1595 LOG_WARN("output: could not allocate queuebuf, dropping fragment\n");
1596 return 0;
1597 }
1598
1599 /* Send fragment */
1600 send_packet();
1601
1602 /* Restore packetbuf from queuebuf */
1603 queuebuf_to_packetbuf(q);
1604 queuebuf_free(q);
1605
1606 /* Check tx result. */
1609 LOG_ERR("output: error in fragment tx, dropping subsequent fragments.\n");
1610 return 0;
1611 }
1612 return 1;
1613}
1614#endif /* SICSLOWPAN_CONF_FRAG */
1615/*--------------------------------------------------------------------*/
1616/** \brief Take an IP packet and format it to be sent on an 802.15.4
1617 * network using 6lowpan.
1618 * \param localdest The MAC address of the destination
1619 *
1620 * The IP packet is initially in uip_buf. Its header is compressed
1621 * and if necessary it is fragmented. The resulting
1622 * packet/fragments are put in packetbuf and delivered to the 802.15.4
1623 * MAC.
1624 */
1625static uint8_t
1626output(const linkaddr_t *localdest)
1627{
1628 int frag_needed;
1629
1630 /* init */
1631 uncomp_hdr_len = 0;
1633
1634 /* reset packetbuf buffer */
1637
1638 if(callback) {
1639 /* call the attribution when the callback comes, but set attributes
1640 here ! */
1641 set_packet_attrs();
1642 }
1643
1644 LOG_INFO("output: sending IPv6 packet with len %d\n", uip_len);
1645
1646 /* copy over the retransmission count from uipbuf attributes */
1647 packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
1648 uipbuf_get_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS));
1649
1650 /* Copy destination address to packetbuf */
1651 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER,
1652 localdest ? localdest : &linkaddr_null);
1653
1654#if LLSEC802154_USES_AUX_HEADER
1655 /* copy LLSEC level */
1656 packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL,
1657 uipbuf_get_attr(UIPBUF_ATTR_LLSEC_LEVEL));
1658#if LLSEC802154_USES_EXPLICIT_KEYS
1659 packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX,
1660 uipbuf_get_attr(UIPBUF_ATTR_LLSEC_KEY_ID));
1661#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
1662#endif /* LLSEC802154_USES_AUX_HEADER */
1663
1664 /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC */
1665 mac_max_payload = NETSTACK_MAC.max_payload();
1666
1667 if(mac_max_payload <= 0) {
1668 /* Framing failed, drop packet */
1669 LOG_WARN("output: failed to calculate payload size - dropping packet\n");
1670 return 0;
1671 }
1672
1673 /* Try to compress the headers */
1674#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
1675 compress_hdr_ipv6();
1676#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
1677#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH
1678 /* Add 6LoRH headers before IPHC. Only needed on routed traffic
1679 (non link-local). */
1680 if(!uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr)) {
1682 add_6lorh_hdr();
1683 }
1684#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_6LORH */
1685#if SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC
1686 if(compress_hdr_iphc() == 0) {
1687 /* Warning should already be issued by function above */
1688 return 0;
1689 }
1690#endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
1691
1692 /* Use the mac_max_payload to understand what is the max payload in a MAC
1693 * packet. We calculate it here only to make a better decision of whether
1694 * the outgoing packet needs to be fragmented or not. */
1695
1696 frag_needed = (int)uip_len - (int)uncomp_hdr_len + (int)packetbuf_hdr_len > mac_max_payload;
1697 LOG_INFO("output: header len %d -> %d, total len %d -> %d, MAC max payload %d, frag_needed %d\n",
1700 mac_max_payload, frag_needed);
1701
1702 if(frag_needed) {
1703#if SICSLOWPAN_CONF_FRAG
1704 /* Number of bytes processed. */
1705 uint16_t processed_ip_out_len;
1706 uint16_t frag_tag;
1707 int curr_frag = 0;
1708
1709 /*
1710 * The outbound IPv6 packet is too large to fit into a single 15.4
1711 * packet, so we fragment it into multiple packets and send them.
1712 * The first fragment contains frag1 dispatch, then IPv6/IPHC/HC_UDP
1713 * dispatchs/headers and IPv6 payload (with len multiple of 8 bytes).
1714 * The subsequent fragments contain the FRAGN dispatch and more of the
1715 * IPv6 payload (still multiple of 8 bytes, except for the last fragment)
1716 */
1717 /* Total IPv6 payload */
1718 int total_payload = (uip_len - uncomp_hdr_len);
1719 /* IPv6 payload that goes to first fragment */
1720 int frag1_payload = (mac_max_payload - packetbuf_hdr_len - SICSLOWPAN_FRAG1_HDR_LEN) & 0xfffffff8;
1721 /* max IPv6 payload in each FRAGN. Must be multiple of 8 bytes */
1722 int fragn_max_payload = (mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN) & 0xfffffff8;
1723 /* max IPv6 payload in the last fragment. Needs not be multiple of 8 bytes */
1724 int last_fragn_max_payload = mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN;
1725 /* sum of all IPv6 payload that goes to non-first and non-last fragments */
1726 int middle_fragn_total_payload = MAX(total_payload - frag1_payload - last_fragn_max_payload, 0);
1727 /* Ceiling of: 2 + middle_fragn_total_payload / fragn_max_payload */
1728 unsigned fragment_count = 2;
1729 if(middle_fragn_total_payload > 0) {
1730 fragment_count += 1 + (middle_fragn_total_payload - 1) / fragn_max_payload;
1731 }
1732
1733 size_t free_bufs = queuebuf_numfree();
1734 LOG_INFO("output: fragmentation needed. fragments: %u, free queuebufs: %zu\n",
1735 fragment_count, free_bufs);
1736
1737 /* Keep one queuebuf in reserve for certain protocol implementations
1738 at other layers. */
1739 size_t needed_bufs = fragment_count + 1;
1740 if(free_bufs < needed_bufs) {
1741 LOG_WARN("output: dropping packet, not enough free bufs (needed: %zu, free: %zu)\n",
1742 needed_bufs, free_bufs);
1743 return 0;
1744 }
1745
1746 if(frag1_payload < 0) {
1747 /* The current implementation requires that all headers fit in the first
1748 * fragment. Here is a corner case where the header did fit packetbuf
1749 * but do no longer fit after truncating for a length multiple of 8. */
1750 LOG_WARN("output: compressed header does not fit first fragment\n");
1751 return 0;
1752 }
1753
1754 /* Reset last tx status -- MAC layers most often call packet_sent asynchrously */
1756 /* Update fragment tag */
1757 frag_tag = my_tag++;
1758
1759 /* Move IPHC/IPv6 header to make room for FRAG1 header */
1760 memmove(packetbuf_ptr + SICSLOWPAN_FRAG1_HDR_LEN, packetbuf_ptr, packetbuf_hdr_len);
1761 packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
1762
1763 /* Set FRAG1 header */
1764 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1765 ((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len));
1766 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG, frag_tag);
1767
1768 /* Set frag1 payload len. Was already caulcated earlier as frag1_payload */
1769 packetbuf_payload_len = frag1_payload;
1770
1771 /* Copy payload from uIP and send fragment */
1772 /* Send fragment */
1773 LOG_INFO("output: fragment %d/%d (tag %d, payload %d)\n",
1774 curr_frag + 1, fragment_count,
1775 frag_tag, packetbuf_payload_len);
1776 if(fragment_copy_payload_and_send(uncomp_hdr_len) == 0) {
1777 return 0;
1778 }
1779
1780 /* Now prepare for subsequent fragments. */
1781
1782 /* FRAGN header: tag was already set at FRAG1. Now set dispatch for all FRAGN */
1783 packetbuf_hdr_len = SICSLOWPAN_FRAGN_HDR_LEN;
1784 SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
1785 ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
1786
1787 /* Keep track of the total length of data sent */
1788 processed_ip_out_len = uncomp_hdr_len + packetbuf_payload_len;
1789
1790 /* Create and send subsequent fragments. */
1791 while(processed_ip_out_len < uip_len) {
1792 curr_frag++;
1793 /* FRAGN header: set offset for this fragment */
1794 PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
1795
1796 /* Calculate fragment len */
1797 if(uip_len - processed_ip_out_len > last_fragn_max_payload) {
1798 /* Not last fragment, send max FRAGN payload */
1799 packetbuf_payload_len = fragn_max_payload;
1800 } else {
1801 /* last fragment */
1802 packetbuf_payload_len = uip_len - processed_ip_out_len;
1803 }
1804
1805 /* Copy payload from uIP and send fragment */
1806 /* Send fragment */
1807 LOG_INFO("output: fragment %d/%d (tag %d, payload %d, offset %d)\n",
1808 curr_frag + 1, fragment_count,
1809 frag_tag, packetbuf_payload_len, processed_ip_out_len);
1810 if(fragment_copy_payload_and_send(processed_ip_out_len) == 0) {
1811 return 0;
1812 }
1813
1814 processed_ip_out_len += packetbuf_payload_len;
1815 }
1816#else /* SICSLOWPAN_CONF_FRAG */
1817 LOG_ERR("output: Packet too large to be sent without fragmentation support; dropping packet\n");
1818 return 0;
1819#endif /* SICSLOWPAN_CONF_FRAG */
1820 } else {
1821 /*
1822 * The packet does not need to be fragmented
1823 * copy "payload" and send
1824 */
1825
1826 if(uip_len < uncomp_hdr_len) {
1827 LOG_ERR("output: uip_len is smaller than uncomp_hdr_len (%d < %d)",
1828 (int)uip_len, (int)uncomp_hdr_len);
1829 return 0;
1830 }
1831
1835 send_packet();
1836 }
1837 return 1;
1838}
1839
1840/*--------------------------------------------------------------------*/
1841/** \brief Process a received 6lowpan packet.
1842 *
1843 * The 6lowpan packet is put in packetbuf by the MAC. If its a frag1 or
1844 * a non-fragmented packet we first uncompress the IP header. The
1845 * 6lowpan payload and possibly the uncompressed IP header are then
1846 * copied in siclowpan_buf. If the IP packet is complete it is copied
1847 * to uip_buf and the IP layer is called.
1848 *
1849 * \note We do not check for overlapping sicslowpan fragments
1850 * (it is a SHALL in the RFC 4944 and should never happen)
1851 */
1852static void
1854{
1855 /* size of the IP packet (read from fragment) */
1856 uint16_t frag_size = 0;
1857 /* offset of the fragment in the IP packet */
1858 uint8_t frag_offset = 0;
1859 uint8_t *buffer;
1860 uint16_t buffer_size;
1861
1862#if SICSLOWPAN_CONF_FRAG
1863 uint8_t is_fragment = 0;
1864 int8_t frag_context = 0;
1865
1866 /* tag of the fragment */
1867 uint16_t frag_tag = 0;
1868 uint8_t first_fragment = 0, last_fragment = 0;
1869#endif /*SICSLOWPAN_CONF_FRAG*/
1870
1871 /* Update link statistics */
1872 link_stats_input_callback(packetbuf_addr(PACKETBUF_ADDR_SENDER));
1873
1874 /* init */
1875 uncomp_hdr_len = 0;
1877
1878 /* The MAC puts the 15.4 payload inside the packetbuf data buffer */
1880
1881 if(packetbuf_datalen() == 0) {
1882 LOG_WARN("input: empty packet\n");
1883 return;
1884 }
1885
1886 /* Clear uipbuf and set default attributes */
1887 uipbuf_clear();
1888
1889 /* This is default uip_buf since we assume that this is not fragmented */
1890 buffer = (uint8_t *)UIP_IP_BUF;
1891 buffer_size = UIP_BUFSIZE;
1892
1893 /* Save the RSSI and LQI of the incoming packet in case the upper layer will
1894 want to query us for it later. */
1895 uipbuf_set_attr(UIPBUF_ATTR_RSSI, packetbuf_attr(PACKETBUF_ATTR_RSSI));
1896 uipbuf_set_attr(UIPBUF_ATTR_LINK_QUALITY, packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY));
1897
1898
1899#if SICSLOWPAN_CONF_FRAG
1900
1901 /*
1902 * Since we don't support the mesh and broadcast header, the first header
1903 * we look for is the fragmentation header
1904 */
1905 switch((GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) >> 8) & SICSLOWPAN_DISPATCH_FRAG_MASK) {
1906 case SICSLOWPAN_DISPATCH_FRAG1:
1907 frag_offset = 0;
1908 frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1909 frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1910 packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
1911 first_fragment = 1;
1912 is_fragment = 1;
1913
1914 LOG_INFO("input: received first element of a fragmented packet (tag %d, len %d)\n",
1915 frag_tag, frag_size);
1916
1917 /* Add the fragment to the fragmentation context */
1918 frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1919
1920 if(frag_context == -1) {
1921 LOG_ERR("input: failed to allocate new reassembly context\n");
1922 return;
1923 }
1924
1925 buffer = frag_info[frag_context].first_frag;
1926 buffer_size = SICSLOWPAN_FIRST_FRAGMENT_SIZE;
1927 break;
1928 case SICSLOWPAN_DISPATCH_FRAGN:
1929 /*
1930 * set offset, tag, size
1931 * Offset is in units of 8 bytes
1932 */
1933 frag_offset = PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET];
1934 frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
1935 frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
1936 packetbuf_hdr_len += SICSLOWPAN_FRAGN_HDR_LEN;
1937
1938 /* Add the fragment to the fragmentation context (this will also
1939 copy the payload) */
1940 frag_context = add_fragment(frag_tag, frag_size, frag_offset);
1941
1942 if(frag_context == -1) {
1943 LOG_ERR("input: reassembly context not found (tag %d)\n", frag_tag);
1944 return;
1945 }
1946
1947 /* Ok - add_fragment will store the fragment automatically - so
1948 we should not store more */
1949 buffer = NULL;
1950
1951 if(frag_info[frag_context].reassembled_len >= frag_size) {
1952 last_fragment = 1;
1953 }
1954 is_fragment = 1;
1955 break;
1956 default:
1957 break;
1958 }
1959
1960 if(is_fragment && !first_fragment) {
1961 /* this is a FRAGN, skip the header compression dispatch section */
1962 goto copypayload;
1963 }
1964#endif /* SICSLOWPAN_CONF_FRAG */
1965
1966 /* First, process 6LoRH headers */
1967 curr_page = 0;
1969 if(curr_page == 1) {
1970 LOG_INFO("input: page 1, 6LoRH\n");
1972 } else if (curr_page > 1) {
1973 LOG_ERR("input: page %u not supported\n", curr_page);
1974 return;
1975 }
1976
1977 /* Process next dispatch and headers */
1978 if(SICSLOWPAN_COMPRESSION > SICSLOWPAN_COMPRESSION_IPV6 &&
1979 (PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK) == SICSLOWPAN_DISPATCH_IPHC) {
1980 LOG_DBG("uncompression: IPHC dispatch\n");
1981 if(uncompress_hdr_iphc(buffer, buffer_size, frag_size) == false) {
1982 LOG_ERR("input: failed to decompress IPHC packet\n");
1983 return;
1984 }
1985 } else if(PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] == SICSLOWPAN_DISPATCH_IPV6) {
1986 LOG_DBG("uncompression: IPV6 dispatch\n");
1987 packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
1988
1989 /* Put uncompressed IP header in sicslowpan_buf. */
1990 memcpy(buffer, packetbuf_ptr + packetbuf_hdr_len, UIP_IPH_LEN);
1991
1992 /* Update uncomp_hdr_len and packetbuf_hdr_len. */
1993 packetbuf_hdr_len += UIP_IPH_LEN;
1994 uncomp_hdr_len += UIP_IPH_LEN;
1995 } else {
1996 LOG_ERR("uncompression: unknown dispatch: 0x%02x, or IPHC disabled\n",
1997 PACKETBUF_6LO_PTR[PACKETBUF_6LO_DISPATCH] & SICSLOWPAN_DISPATCH_IPHC_MASK);
1998 return;
1999 }
2000
2001#if SICSLOWPAN_CONF_FRAG
2002 copypayload:
2003#endif /*SICSLOWPAN_CONF_FRAG*/
2004 /*
2005 * copy "payload" from the packetbuf buffer to the sicslowpan_buf
2006 * if this is a first fragment or not fragmented packet,
2007 * we have already copied the compressed headers, uncomp_hdr_len
2008 * and packetbuf_hdr_len are non 0, frag_offset is.
2009 * If this is a subsequent fragment, this is the contrary.
2010 */
2012 LOG_ERR("input: packet dropped due to header > total packet\n");
2013 return;
2014 }
2016
2017#if SICSLOWPAN_CONF_FRAG
2018 if(is_fragment) {
2019 LOG_INFO("input: fragment (tag %d, payload %d, offset %d) -- %u %u\n",
2020 frag_tag, packetbuf_payload_len, frag_offset << 3, packetbuf_datalen(), packetbuf_hdr_len);
2021 }
2022#endif /*SICSLOWPAN_CONF_FRAG*/
2023
2024 /* Sanity-check size of incoming packet to avoid buffer overflow */
2025 {
2026 unsigned int req_size = uncomp_hdr_len + (uint16_t)(frag_offset << 3)
2028 if(req_size > sizeof(uip_buf)) {
2029#if SICSLOWPAN_CONF_FRAG
2030 LOG_ERR(
2031 "input: packet and fragment context %u dropped, minimum required IP_BUF size: %d+%d+%d=%u (current size: %u)\n",
2032 frag_context,
2033 uncomp_hdr_len, (uint16_t)(frag_offset << 3),
2034 packetbuf_payload_len, req_size, (unsigned)sizeof(uip_buf));
2035 /* Discard all fragments for this contex, as reassembling this particular fragment would
2036 * cause an overflow in uipbuf */
2037 clear_fragments(frag_context);
2038#endif /* SICSLOWPAN_CONF_FRAG */
2039 return;
2040 }
2041 }
2042
2043 /* copy the payload if buffer is non-null - which is only the case with first fragment
2044 or packets that are non fragmented */
2045 if(buffer != NULL) {
2046 if(uncomp_hdr_len + packetbuf_payload_len > buffer_size) {
2047 LOG_ERR("input: cannot copy the payload into the buffer\n");
2048 return;
2049 }
2051 }
2052
2053 /* update processed_ip_in_len if fragment, sicslowpan_len otherwise */
2054
2055#if SICSLOWPAN_CONF_FRAG
2056 if(frag_size > 0) {
2057 /* Add the size of the header only for the first fragment. */
2058 if(first_fragment != 0) {
2059 frag_info[frag_context].reassembled_len = uncomp_hdr_len + packetbuf_payload_len;
2060 frag_info[frag_context].first_frag_len = uncomp_hdr_len + packetbuf_payload_len;
2061 }
2062 /* For the last fragment, we are OK if there is extrenous bytes at
2063 the end of the packet. */
2064 if(last_fragment != 0) {
2065 frag_info[frag_context].reassembled_len = frag_size;
2066 /* copy to uip */
2067 if(!copy_frags2uip(frag_context)) {
2068 return;
2069 }
2070 }
2071 }
2072
2073 /*
2074 * If we have a full IP packet in sicslowpan_buf, deliver it to
2075 * the IP stack
2076 */
2077 if(!is_fragment || last_fragment) {
2078 /* packet is in uip already - just set length */
2079 if(is_fragment != 0 && last_fragment != 0) {
2080 uip_len = frag_size;
2081 } else {
2083 }
2084#else
2086#endif /* SICSLOWPAN_CONF_FRAG */
2087 LOG_INFO("input: received IPv6 packet with len %d\n",
2088 uip_len);
2089
2090 if(LOG_DBG_ENABLED) {
2091 uint16_t ndx;
2092 LOG_DBG("uncompression: after (%u):", UIP_IP_BUF->len[1]);
2093 for (ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
2094 uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
2095 LOG_DBG_("%02x", data);
2096 }
2097 LOG_DBG_("\n");
2098 }
2099
2100 /* if callback is set then set attributes and call */
2101 if(callback) {
2102 set_packet_attrs();
2103 callback->input_callback();
2104 }
2105
2106#if LLSEC802154_USES_AUX_HEADER
2107 /*
2108 * Assuming that the last packet in packetbuf is containing
2109 * the LLSEC state so that it can be copied to uipbuf.
2110 */
2111 uipbuf_set_attr(UIPBUF_ATTR_LLSEC_LEVEL,
2112 packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL));
2113#if LLSEC802154_USES_EXPLICIT_KEYS
2114 uipbuf_set_attr(UIPBUF_ATTR_LLSEC_KEY_ID,
2115 packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX));
2116#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
2117#endif /* LLSEC802154_USES_AUX_HEADER */
2118
2119 tcpip_input();
2120#if SICSLOWPAN_CONF_FRAG
2121 }
2122#endif /* SICSLOWPAN_CONF_FRAG */
2123}
2124/** @} */
2125
2126/*--------------------------------------------------------------------*/
2127/* \brief 6lowpan init function (called by the MAC layer) */
2128/*--------------------------------------------------------------------*/
2129void
2130sicslowpan_init(void)
2131{
2132
2133#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC
2134/* Preinitialize any address contexts for better header compression
2135 * (Saves up to 13 bytes per 6lowpan packet)
2136 * The platform contiki-conf.h file can override this using e.g.
2137 * #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xbb;addr_contexts[0].prefix[1]=0xbb;}
2138 */
2139#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
2140 addr_contexts[0].used = 1;
2141 addr_contexts[0].number = 0;
2142#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0
2143 SICSLOWPAN_CONF_ADDR_CONTEXT_0;
2144#else
2145 addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0;
2146 addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1;
2147#endif
2148#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
2149
2150#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1
2151 {
2152 int i;
2153 for(i = 1; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
2154#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1
2155 if (i==1) {
2156 addr_contexts[1].used = 1;
2157 addr_contexts[1].number = 1;
2158 SICSLOWPAN_CONF_ADDR_CONTEXT_1;
2159#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
2160 } else if (i==2) {
2161 addr_contexts[2].used = 1;
2162 addr_contexts[2].number = 2;
2163 SICSLOWPAN_CONF_ADDR_CONTEXT_2;
2164#endif
2165 } else {
2166 addr_contexts[i].used = 0;
2167 }
2168#else
2169 addr_contexts[i].used = 0;
2170#endif /* SICSLOWPAN_CONF_ADDR_CONTEXT_1 */
2171 }
2172 }
2173#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */
2174
2175#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC */
2176}
2177/*--------------------------------------------------------------------*/
2178const struct network_driver sicslowpan_driver = {
2179 "sicslowpan",
2180 sicslowpan_init,
2181 input,
2182 output
2183};
2184/*--------------------------------------------------------------------*/
2185/** @} */
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:103
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: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: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.