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