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