2008-10-14 11:42:33 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2008, Swedish Institute of Computer Science.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. Neither the name of the Institute nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* This file is part of the Contiki operating system.
|
|
|
|
*
|
|
|
|
*/
|
2014-11-08 01:15:42 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/**
|
|
|
|
* \file
|
2010-02-25 16:50:58 +01:00
|
|
|
* 6lowpan implementation (RFC4944 and draft-ietf-6lowpan-hc-06)
|
2008-10-14 11:42:33 +02:00
|
|
|
*
|
|
|
|
* \author Adam Dunkels <adam@sics.se>
|
|
|
|
* \author Nicolas Tsiftes <nvt@sics.se>
|
|
|
|
* \author Niclas Finne <nfi@sics.se>
|
|
|
|
* \author Mathilde Durvy <mdurvy@cisco.com>
|
|
|
|
* \author Julien Abeille <jabeille@cisco.com>
|
2010-02-25 16:50:58 +01:00
|
|
|
* \author Joakim Eriksson <joakime@sics.se>
|
2010-03-26 11:28:51 +01:00
|
|
|
* \author Joel Hoglund <joel@sics.se>
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
|
|
|
|
2014-11-08 01:15:42 +01:00
|
|
|
/**
|
|
|
|
* \addtogroup sicslowpan
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2010-03-09 16:18:03 +01:00
|
|
|
/**
|
|
|
|
* FOR HC-06 COMPLIANCE TODO:
|
|
|
|
* -Add compression options to UDP, currently only supports
|
|
|
|
* both ports compressed or both ports elided
|
2015-10-30 11:41:59 +01:00
|
|
|
*
|
2010-03-09 17:19:44 +01:00
|
|
|
* -Verify TC/FL compression works
|
2015-10-30 11:41:59 +01:00
|
|
|
*
|
2010-03-09 16:18:03 +01:00
|
|
|
* -Add stateless multicast option
|
|
|
|
*/
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
#include <string.h>
|
|
|
|
|
2009-04-06 15:11:20 +02:00
|
|
|
#include "contiki.h"
|
2010-02-08 22:59:21 +01:00
|
|
|
#include "dev/watchdog.h"
|
2013-11-22 09:17:54 +01:00
|
|
|
#include "net/ip/tcpip.h"
|
|
|
|
#include "net/ip/uip.h"
|
|
|
|
#include "net/ipv6/uip-ds6.h"
|
2013-12-12 20:50:07 +01:00
|
|
|
#include "net/rime/rime.h"
|
2013-11-22 09:17:54 +01:00
|
|
|
#include "net/ipv6/sicslowpan.h"
|
A work-in-progress rework of the Contiki MAC and radio layers. The
main ideas are:
* Separates the Contiki low-layer network stack into four layers:
network (e.g. sicslowpan / rime), Medium Access Control MAC
(e.g. CSMA), Radio Duty Cycling RDC (e.g. ContikiMAC, X-MAC), and
radio (e.g. cc2420).
* Introduces a new way to configure the network stack. Four #defines
that specify what mechanism/protocol/driver to use at the four
layers: NETSTACK_CONF_NETWORK, NETSTACK_CONF_MAC, NETSTACK_CONF_RDC,
NETSTACK_CONF_RADIO.
* Adds a callback mechanism to inform the MAC and network layers about
the fate of a transmitted packet: if the packet was not possible to
transmit, the cause of the failure is reported, and if the packets
was successfully transmitted, the number of tries before it was
finally transmitted is reported.
* NULL-protocols at both the MAC and RDC layers: nullmac and nullrdc,
which can be used when MAC and RDC functionality is not needed.
* Extends the radio API with three new functions that enable more
efficient radio duty cycling protocols: channel check, pending
packet, and receiving packet.
* New initialization mechanism, which takes advantage of the NETSTACK
#defines.
2010-02-18 22:48:39 +01:00
|
|
|
#include "net/netstack.h"
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2013-03-17 23:21:30 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2013-05-15 11:42:17 +02:00
|
|
|
#define DEBUG DEBUG_NONE
|
2013-11-22 09:17:54 +01:00
|
|
|
#include "net/ip/uip-debug.h"
|
2008-10-14 11:42:33 +02:00
|
|
|
#if DEBUG
|
2009-07-10 15:33:45 +02:00
|
|
|
/* PRINTFI and PRINTFO are defined for input and output to debug one without changing the timing of the other */
|
2012-02-17 23:45:13 +01:00
|
|
|
uint8_t p;
|
2008-10-14 11:42:33 +02:00
|
|
|
#include <stdio.h>
|
2013-05-15 11:42:17 +02:00
|
|
|
#define PRINTFI(...) PRINTF(__VA_ARGS__)
|
|
|
|
#define PRINTFO(...) PRINTF(__VA_ARGS__)
|
2008-10-14 11:42:33 +02:00
|
|
|
#else
|
2009-07-10 15:33:45 +02:00
|
|
|
#define PRINTFI(...)
|
|
|
|
#define PRINTFO(...)
|
2008-10-14 11:42:33 +02:00
|
|
|
#endif /* DEBUG == 1*/
|
|
|
|
|
|
|
|
#if UIP_LOGGING
|
|
|
|
#include <stdio.h>
|
|
|
|
void uip_log(char *msg);
|
|
|
|
#define UIP_LOG(m) uip_log(m)
|
|
|
|
#else
|
|
|
|
#define UIP_LOG(m)
|
|
|
|
#endif /* UIP_LOGGING == 1 */
|
|
|
|
|
2010-10-26 15:25:32 +02:00
|
|
|
#ifdef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS
|
|
|
|
#define SICSLOWPAN_MAX_MAC_TRANSMISSIONS SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS
|
|
|
|
#else
|
2011-02-10 22:47:45 +01:00
|
|
|
#define SICSLOWPAN_MAX_MAC_TRANSMISSIONS 4
|
2010-10-26 15:25:32 +02:00
|
|
|
#endif
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#ifndef SICSLOWPAN_COMPRESSION
|
|
|
|
#ifdef SICSLOWPAN_CONF_COMPRESSION
|
|
|
|
#define SICSLOWPAN_COMPRESSION SICSLOWPAN_CONF_COMPRESSION
|
|
|
|
#else
|
|
|
|
#define SICSLOWPAN_COMPRESSION SICSLOWPAN_COMPRESSION_IPV6
|
|
|
|
#endif /* SICSLOWPAN_CONF_COMPRESSION */
|
|
|
|
#endif /* SICSLOWPAN_COMPRESSION */
|
|
|
|
|
2009-04-06 15:11:20 +02:00
|
|
|
#define GET16(ptr,index) (((uint16_t)((ptr)[index] << 8)) | ((ptr)[(index) + 1]))
|
|
|
|
#define SET16(ptr,index,value) do { \
|
|
|
|
(ptr)[index] = ((value) >> 8) & 0xff; \
|
|
|
|
(ptr)[index + 1] = (value) & 0xff; \
|
|
|
|
} while(0)
|
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
/** \name Pointers in the packetbuf buffer
|
2008-10-14 11:42:33 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
#define PACKETBUF_FRAG_PTR (packetbuf_ptr)
|
|
|
|
#define PACKETBUF_FRAG_DISPATCH_SIZE 0 /* 16 bit */
|
|
|
|
#define PACKETBUF_FRAG_TAG 2 /* 16 bit */
|
|
|
|
#define PACKETBUF_FRAG_OFFSET 4 /* 8 bit */
|
2009-04-06 15:11:20 +02:00
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
/* define the buffer as a byte array */
|
2013-12-13 00:09:44 +01:00
|
|
|
#define PACKETBUF_IPHC_BUF ((uint8_t *)(packetbuf_ptr + packetbuf_hdr_len))
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
#define PACKETBUF_HC1_PTR (packetbuf_ptr + packetbuf_hdr_len)
|
|
|
|
#define PACKETBUF_HC1_DISPATCH 0 /* 8 bit */
|
|
|
|
#define PACKETBUF_HC1_ENCODING 1 /* 8 bit */
|
|
|
|
#define PACKETBUF_HC1_TTL 2 /* 8 bit */
|
2009-04-06 15:11:20 +02:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
#define PACKETBUF_HC1_HC_UDP_PTR (packetbuf_ptr + packetbuf_hdr_len)
|
|
|
|
#define PACKETBUF_HC1_HC_UDP_DISPATCH 0 /* 8 bit */
|
|
|
|
#define PACKETBUF_HC1_HC_UDP_HC1_ENCODING 1 /* 8 bit */
|
|
|
|
#define PACKETBUF_HC1_HC_UDP_UDP_ENCODING 2 /* 8 bit */
|
|
|
|
#define PACKETBUF_HC1_HC_UDP_TTL 3 /* 8 bit */
|
|
|
|
#define PACKETBUF_HC1_HC_UDP_PORTS 4 /* 8 bit */
|
|
|
|
#define PACKETBUF_HC1_HC_UDP_CHKSUM 5 /* 16 bit */
|
2009-04-06 15:11:20 +02:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/** \name Pointers in the sicslowpan and uip buffer
|
|
|
|
* @{
|
|
|
|
*/
|
2015-09-14 15:55:26 +02:00
|
|
|
|
|
|
|
/* NOTE: In the multiple-reassembly context there is only room for the header / first fragment */
|
|
|
|
#define SICSLOWPAN_IP_BUF(buf) ((struct uip_ip_hdr *)buf)
|
|
|
|
#define SICSLOWPAN_UDP_BUF(buf) ((struct uip_udp_hdr *)&buf[UIP_IPH_LEN])
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
|
|
|
|
#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
|
2010-04-01 12:01:01 +02:00
|
|
|
#define UIP_TCP_BUF ((struct uip_tcp_hdr *)&uip_buf[UIP_LLIPH_LEN])
|
2011-10-13 15:09:40 +02:00
|
|
|
#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN])
|
2008-10-14 11:42:33 +02:00
|
|
|
/** @} */
|
|
|
|
|
|
|
|
|
2014-02-09 15:02:55 +01:00
|
|
|
/** \brief Maximum available size for frame headers,
|
|
|
|
link layer security-related overhead, as well as
|
|
|
|
6LoWPAN payload. */
|
2013-03-17 23:55:01 +01:00
|
|
|
#ifdef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
|
|
|
|
#define MAC_MAX_PAYLOAD SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
|
|
|
|
#else /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
|
2014-02-09 15:02:55 +01:00
|
|
|
#define MAC_MAX_PAYLOAD (127 - 2)
|
2013-03-17 23:55:01 +01:00
|
|
|
#endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2011-09-02 13:51:09 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/** \brief Some MAC layers need a minimum payload, which is configurable
|
|
|
|
through the SICSLOWPAN_CONF_COMPRESSION_THRESHOLD option. */
|
2011-09-02 13:51:09 +02:00
|
|
|
#ifdef SICSLOWPAN_CONF_COMPRESSION_THRESHOLD
|
|
|
|
#define COMPRESSION_THRESHOLD SICSLOWPAN_CONF_COMPRESSION_THRESHOLD
|
|
|
|
#else
|
|
|
|
#define COMPRESSION_THRESHOLD 0
|
|
|
|
#endif
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/** \name General variables
|
|
|
|
* @{
|
|
|
|
*/
|
2010-03-17 13:08:59 +01:00
|
|
|
|
2008-10-14 14:26:18 +02:00
|
|
|
/**
|
2013-12-13 00:09:44 +01:00
|
|
|
* A pointer to the packetbuf buffer.
|
|
|
|
* We initialize it to the beginning of the packetbuf buffer, then
|
|
|
|
* access different fields by updating the offset packetbuf_hdr_len.
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
static uint8_t *packetbuf_ptr;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/**
|
2013-12-13 00:09:44 +01:00
|
|
|
* packetbuf_hdr_len is the total length of (the processed) 6lowpan headers
|
2008-10-14 11:42:33 +02:00
|
|
|
* (fragment headers, IPV6 or HC1, HC2, and HC1 and HC2 non compressed
|
2008-10-14 14:26:18 +02:00
|
|
|
* fields).
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
static uint8_t packetbuf_hdr_len;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/**
|
2013-12-13 00:09:44 +01:00
|
|
|
* The length of the payload in the Packetbuf buffer.
|
2008-10-14 14:26:18 +02:00
|
|
|
* The payload is what comes after the compressed or uncompressed
|
2008-10-14 11:42:33 +02:00
|
|
|
* headers (can be the IP payload if the IP header only is compressed
|
2008-10-14 14:26:18 +02:00
|
|
|
* or the UDP payload if the UDP header is also compressed)
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
static int packetbuf_payload_len;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* uncomp_hdr_len is the length of the headers before compression (if HC2
|
|
|
|
* is used this includes the UDP header in addition to the IP header).
|
|
|
|
*/
|
2012-02-17 23:45:13 +01:00
|
|
|
static uint8_t uncomp_hdr_len;
|
2012-03-26 23:37:17 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* the result of the last transmitted fragment
|
|
|
|
*/
|
|
|
|
static int last_tx_status;
|
2008-10-14 11:42:33 +02:00
|
|
|
/** @} */
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
static int last_rssi;
|
2010-05-24 16:28:56 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/* ----------------------------------------------------------------- */
|
|
|
|
/* Support for reassembling multiple packets */
|
|
|
|
/* ----------------------------------------------------------------- */
|
2015-09-18 14:22:17 +02:00
|
|
|
|
2015-09-14 17:34:08 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
static uint16_t my_tag;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/** The total length of the IPv6 packet in the sicslowpan_buf. */
|
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/* This needs to be defined in NBR / Nodes depending on available RAM */
|
|
|
|
/* and expected reassembly requirements */
|
|
|
|
#ifdef SICSLOWPAN_CONF_FRAGMENT_BUFFERS
|
|
|
|
#define SICSLOWPAN_FRAGMENT_BUFFERS SICSLOWPAN_CONF_FRAGMENT_BUFFERS
|
|
|
|
#else
|
|
|
|
#define SICSLOWPAN_FRAGMENT_BUFFERS 12
|
|
|
|
#endif
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/* REASS_CONTEXTS corresponds to the number of simultaneous
|
|
|
|
* reassemblies that can be made. NOTE: the first buffer for each
|
|
|
|
* reassembly is stored in the context since it can be larger than the
|
|
|
|
* rest of the fragments due to header compression.
|
|
|
|
**/
|
|
|
|
#ifdef SICSLOWPAN_CONF_REASS_CONTEXTS
|
|
|
|
#define SICSLOWPAN_REASS_CONTEXTS SICSLOWPAN_CONF_REASS_CONTEXTS
|
|
|
|
#else
|
|
|
|
#define SICSLOWPAN_REASS_CONTEXTS 2
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* The size of each fragment (IP payload) for the 6lowpan fragmentation */
|
|
|
|
#ifdef SICSLOWPAN_CONF_FRAGMENT_SIZE
|
|
|
|
#define SICSLOWPAN_FRAGMENT_SIZE SICSLOWPAN_CONF_FRAGMENT_SIZE
|
|
|
|
#else
|
|
|
|
#define SICSLOWPAN_FRAGMENT_SIZE 110
|
|
|
|
#endif
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/* Assuming that the worst growth for uncompression is 38 bytes */
|
|
|
|
#define SICSLOWPAN_FIRST_FRAGMENT_SIZE (SICSLOWPAN_FRAGMENT_SIZE + 38)
|
|
|
|
|
|
|
|
/* all information needed for reassembly */
|
|
|
|
struct sicslowpan_frag_info {
|
|
|
|
/** When reassembling, the source address of the fragments being merged */
|
|
|
|
linkaddr_t sender;
|
|
|
|
/** The destination address of the fragments being merged */
|
|
|
|
linkaddr_t receiver;
|
|
|
|
/** When reassembling, the tag in the fragments being merged. */
|
|
|
|
uint16_t tag;
|
|
|
|
/** Total length of the fragmented packet */
|
|
|
|
uint16_t len;
|
|
|
|
/** Current length of reassembled fragments */
|
|
|
|
uint16_t reassembled_len;
|
|
|
|
/** Reassembly %process %timer. */
|
|
|
|
struct timer reass_timer;
|
|
|
|
|
|
|
|
/** Fragment size of first fragment */
|
|
|
|
uint16_t first_frag_len;
|
|
|
|
/** First fragment - needs a larger buffer since the size is uncompressed size
|
|
|
|
and we need to know total size to know when we have received last fragment. */
|
|
|
|
uint8_t first_frag[SICSLOWPAN_FIRST_FRAGMENT_SIZE];
|
|
|
|
};
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
static struct sicslowpan_frag_info frag_info[SICSLOWPAN_REASS_CONTEXTS];
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
struct sicslowpan_frag_buf {
|
|
|
|
/* the index of the frag_info */
|
|
|
|
uint8_t index;
|
|
|
|
/* Fragment offset */
|
|
|
|
uint8_t offset;
|
|
|
|
/* Length of this fragment (if zero this buffer is not allocated) */
|
|
|
|
uint8_t len;
|
|
|
|
uint8_t data[SICSLOWPAN_FRAGMENT_SIZE];
|
|
|
|
};
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
static struct sicslowpan_frag_buf frag_buf[SICSLOWPAN_FRAGMENT_BUFFERS];
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static int
|
|
|
|
clear_fragments(uint8_t frag_info_index)
|
|
|
|
{
|
|
|
|
int i, clear_count;
|
|
|
|
clear_count = 0;
|
|
|
|
frag_info[frag_info_index].len = 0;
|
|
|
|
for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
|
|
|
|
if(frag_buf[i].len > 0 && frag_buf[i].index == frag_info_index) {
|
|
|
|
/* deallocate the buffer */
|
|
|
|
frag_buf[i].len = 0;
|
|
|
|
clear_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return clear_count;
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static int
|
|
|
|
timeout_fragments(int not_context)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int count = 0;
|
|
|
|
for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
|
|
|
|
if(frag_info[i].len > 0 && i != not_context &&
|
|
|
|
timer_expired(&frag_info[i].reass_timer)) {
|
|
|
|
/* This context can be freed */
|
|
|
|
count += clear_fragments(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static int
|
|
|
|
store_fragment(uint8_t index, uint8_t offset)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
|
|
|
|
if(frag_buf[i].len == 0) {
|
|
|
|
/* copy over the data from packetbuf into the fragment buffer and store offset and len */
|
|
|
|
frag_buf[i].offset = offset; /* frag offset */
|
|
|
|
frag_buf[i].len = packetbuf_datalen() - packetbuf_hdr_len;
|
|
|
|
frag_buf[i].index = index;
|
|
|
|
memcpy(frag_buf[i].data, packetbuf_ptr + packetbuf_hdr_len,
|
|
|
|
packetbuf_datalen() - packetbuf_hdr_len);
|
|
|
|
|
|
|
|
PRINTF("Fragsize: %d\n", frag_buf[i].len);
|
|
|
|
/* return the length of the stored fragment */
|
|
|
|
return frag_buf[i].len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* failed */
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
/* add a new fragment to the buffer */
|
|
|
|
static int8_t
|
|
|
|
add_fragment(uint16_t tag, uint16_t frag_size, uint8_t offset)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int len;
|
|
|
|
int8_t found = -1;
|
|
|
|
|
|
|
|
if(offset == 0) {
|
|
|
|
/* This is a first fragment - check if we can add this */
|
|
|
|
for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
|
|
|
|
/* clear all fragment info with expired timer to free all fragment buffers */
|
|
|
|
if(frag_info[i].len > 0 && timer_expired(&frag_info[i].reass_timer)) {
|
|
|
|
clear_fragments(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We use len as indication on used or not used */
|
|
|
|
if(found < 0 && frag_info[i].len == 0) {
|
|
|
|
/* We remember the first free fragment info but must continue
|
|
|
|
the loop to free any other expired fragment buffers. */
|
|
|
|
found = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(found < 0) {
|
|
|
|
PRINTF("*** Failed to store new fragment session - tag: %d\n", tag);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Found a free fragment info to store data in */
|
|
|
|
frag_info[found].len = frag_size;
|
|
|
|
frag_info[found].tag = tag;
|
|
|
|
linkaddr_copy(&frag_info[found].sender,
|
|
|
|
packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
|
|
|
timer_set(&frag_info[found].reass_timer, SICSLOWPAN_REASS_MAXAGE * CLOCK_SECOND / 16);
|
|
|
|
/* first fragment can not be stored immediately but is moved into
|
|
|
|
the buffer while uncompressing */
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is a N-fragment - should find the info */
|
|
|
|
for(i = 0; i < SICSLOWPAN_REASS_CONTEXTS; i++) {
|
|
|
|
if(frag_info[i].tag == tag && frag_info[i].len > 0 &&
|
|
|
|
linkaddr_cmp(&frag_info[i].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
|
|
|
|
/* Tag and Sender match - this must be the correct info to store in */
|
|
|
|
found = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(found < 0) {
|
|
|
|
/* no entry found for storing the new fragment */
|
|
|
|
PRINTF("*** Failed to store N-fragment - could not find session - tag: %d offset: %d\n", tag, offset);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* i is the index of the reassembly context */
|
|
|
|
len = store_fragment(i, offset);
|
|
|
|
if(len < 0 && timeout_fragments(i) > 0) {
|
|
|
|
len = store_fragment(i, offset);
|
|
|
|
}
|
|
|
|
if(len > 0) {
|
|
|
|
frag_info[i].reassembled_len += len;
|
|
|
|
return i;
|
|
|
|
} else {
|
2015-09-18 14:22:17 +02:00
|
|
|
/* should we also clear all fragments since we failed to store
|
|
|
|
this fragment? */
|
2015-09-14 15:55:26 +02:00
|
|
|
PRINTF("*** Failed to store fragment - packet reassembly will fail tag:%d l\n", frag_info[i].tag);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
2015-09-18 14:22:17 +02:00
|
|
|
/* Copy all the fragments that are associated with a specific context
|
|
|
|
into uip */
|
2015-09-14 15:55:26 +02:00
|
|
|
static void
|
|
|
|
copy_frags2uip(int context)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Copy from the fragment context info buffer first */
|
|
|
|
memcpy((uint8_t *)UIP_IP_BUF, (uint8_t *)frag_info[context].first_frag,
|
|
|
|
frag_info[context].first_frag_len);
|
|
|
|
for(i = 0; i < SICSLOWPAN_FRAGMENT_BUFFERS; i++) {
|
|
|
|
/* And also copy all matching fragments */
|
|
|
|
if(frag_buf[i].len > 0 && frag_buf[i].index == context) {
|
|
|
|
memcpy((uint8_t *)UIP_IP_BUF + (uint16_t)(frag_buf[i].offset << 3),
|
|
|
|
(uint8_t *)frag_buf[i].data, frag_buf[i].len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* deallocate all the fragments for this context */
|
|
|
|
clear_fragments(context);
|
|
|
|
}
|
2015-09-14 17:34:08 +02:00
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
2015-09-14 15:55:26 +02:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
2013-11-22 15:10:44 +01:00
|
|
|
|
2011-10-13 15:09:40 +02:00
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
/* Rime Sniffer support for one single listener to enable powertrace of IP */
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
static struct rime_sniffer *callback = NULL;
|
|
|
|
|
|
|
|
void
|
2011-10-20 12:37:56 +02:00
|
|
|
rime_sniffer_add(struct rime_sniffer *s)
|
|
|
|
{
|
2011-10-13 15:09:40 +02:00
|
|
|
callback = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-10-20 12:37:56 +02:00
|
|
|
rime_sniffer_remove(struct rime_sniffer *s)
|
|
|
|
{
|
2011-10-13 15:09:40 +02:00
|
|
|
callback = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-10-20 12:37:56 +02:00
|
|
|
set_packet_attrs()
|
|
|
|
{
|
2011-10-13 15:09:40 +02:00
|
|
|
int c = 0;
|
|
|
|
/* set protocol in NETWORK_ID */
|
|
|
|
packetbuf_set_attr(PACKETBUF_ATTR_NETWORK_ID, UIP_IP_BUF->proto);
|
|
|
|
|
|
|
|
/* assign values to the channel attribute (port or type + code) */
|
|
|
|
if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
|
|
|
|
c = UIP_UDP_BUF->srcport;
|
|
|
|
if(UIP_UDP_BUF->destport < c) {
|
|
|
|
c = UIP_UDP_BUF->destport;
|
|
|
|
}
|
|
|
|
} else if(UIP_IP_BUF->proto == UIP_PROTO_TCP) {
|
|
|
|
c = UIP_TCP_BUF->srcport;
|
|
|
|
if(UIP_TCP_BUF->destport < c) {
|
|
|
|
c = UIP_TCP_BUF->destport;
|
|
|
|
}
|
|
|
|
} else if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6) {
|
|
|
|
c = UIP_ICMP_BUF->type << 8 | UIP_ICMP_BUF->icode;
|
|
|
|
}
|
|
|
|
|
|
|
|
packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, c);
|
|
|
|
|
|
|
|
/* if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { */
|
|
|
|
/* own = 1; */
|
|
|
|
/* } */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
|
|
|
|
/** \name HC06 specific variables
|
2008-10-14 11:42:33 +02:00
|
|
|
* @{
|
|
|
|
*/
|
2010-03-19 09:15:20 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/** Addresses contexts for IPHC. */
|
2010-03-19 13:54:38 +01:00
|
|
|
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
2015-10-30 11:41:59 +01:00
|
|
|
static struct sicslowpan_addr_context
|
2008-10-14 11:42:33 +02:00
|
|
|
addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
|
2010-03-19 09:15:20 +01:00
|
|
|
#endif
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/** pointer to an address context. */
|
|
|
|
static struct sicslowpan_addr_context *context;
|
|
|
|
|
|
|
|
/** pointer to the byte where to write next inline field. */
|
2010-03-16 11:21:04 +01:00
|
|
|
static uint8_t *hc06_ptr;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-18 14:22:17 +02:00
|
|
|
/* Uncompression of linklocal */
|
2010-06-06 14:44:12 +02:00
|
|
|
/* 0 -> 16 bytes from packet */
|
|
|
|
/* 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet */
|
2011-03-06 22:34:16 +01:00
|
|
|
/* 2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet */
|
2010-06-06 14:44:12 +02:00
|
|
|
/* 3 -> 2 bytes from prefix - infer 8 bytes from lladdr */
|
2010-05-31 22:42:27 +02:00
|
|
|
/* NOTE: => the uncompress function does change 0xf to 0x10 */
|
2010-06-06 14:44:12 +02:00
|
|
|
/* NOTE: 0x00 => no-autoconfig => unspecified */
|
2010-05-31 22:42:27 +02:00
|
|
|
const uint8_t unc_llconf[] = {0x0f,0x28,0x22,0x20};
|
2010-06-06 14:44:12 +02:00
|
|
|
|
|
|
|
/* Uncompression of ctx-based */
|
|
|
|
/* 0 -> 0 bits from packet [unspecified / reserved] */
|
|
|
|
/* 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet */
|
2011-03-06 22:34:16 +01:00
|
|
|
/* 2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX + 2 from packet */
|
2010-06-06 14:44:12 +02:00
|
|
|
/* 3 -> 8 bytes from prefix - infer 8 bytes from lladdr */
|
|
|
|
const uint8_t unc_ctxconf[] = {0x00,0x88,0x82,0x80};
|
|
|
|
|
|
|
|
/* Uncompression of ctx-based */
|
|
|
|
/* 0 -> 0 bits from packet */
|
|
|
|
/* 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet */
|
|
|
|
/* 2 -> 2 bytes from prefix - zeroes + 3 from packet */
|
|
|
|
/* 3 -> 2 bytes from prefix - infer 1 bytes from lladdr */
|
2010-05-31 22:42:27 +02:00
|
|
|
const uint8_t unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
|
|
|
|
|
|
|
|
/* Link local prefix */
|
|
|
|
const uint8_t llprefix[] = {0xfe, 0x80};
|
|
|
|
|
|
|
|
/* TTL uncompression values */
|
2010-06-01 14:37:54 +02:00
|
|
|
static const uint8_t ttl_values[] = {0, 1, 64, 255};
|
2010-05-31 22:42:27 +02:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/*--------------------------------------------------------------------*/
|
2015-09-14 15:55:26 +02:00
|
|
|
/** \name IPHC related functions
|
2008-10-14 11:42:33 +02:00
|
|
|
* @{ */
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/** \brief find the context corresponding to prefix ipaddr */
|
2008-10-14 14:26:18 +02:00
|
|
|
static struct sicslowpan_addr_context*
|
2010-11-02 11:56:57 +01:00
|
|
|
addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr)
|
|
|
|
{
|
2010-05-31 22:42:27 +02:00
|
|
|
/* Remove code to avoid warnings and save flash if no context is used */
|
2010-03-19 13:54:38 +01:00
|
|
|
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
2010-03-19 09:15:20 +01:00
|
|
|
int i;
|
2008-10-14 11:42:33 +02:00
|
|
|
for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
|
|
|
|
if((addr_contexts[i].used == 1) &&
|
|
|
|
uip_ipaddr_prefixcmp(&addr_contexts[i].prefix, ipaddr, 64)) {
|
|
|
|
return &addr_contexts[i];
|
2008-10-14 14:26:18 +02:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2010-03-19 13:54:38 +01:00
|
|
|
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
|
2008-10-14 11:42:33 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/** \brief find the context with the given number */
|
2008-10-14 14:26:18 +02:00
|
|
|
static struct sicslowpan_addr_context*
|
2012-02-17 23:45:13 +01:00
|
|
|
addr_context_lookup_by_number(uint8_t number)
|
2010-11-02 11:56:57 +01:00
|
|
|
{
|
2015-10-30 11:41:59 +01:00
|
|
|
/* Remove code to avoid warnings and save flash if no context is used */
|
2010-03-19 13:54:38 +01:00
|
|
|
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
2010-03-19 09:15:20 +01:00
|
|
|
int i;
|
2008-10-14 11:42:33 +02:00
|
|
|
for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
|
|
|
|
if((addr_contexts[i].used == 1) &&
|
|
|
|
addr_contexts[i].number == number) {
|
|
|
|
return &addr_contexts[i];
|
2008-10-14 14:26:18 +02:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2010-03-19 13:54:38 +01:00
|
|
|
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
|
2008-10-14 11:42:33 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
2010-03-16 11:21:04 +01:00
|
|
|
/*--------------------------------------------------------------------*/
|
2010-05-24 16:28:56 +02:00
|
|
|
static uint8_t
|
2010-11-02 11:56:57 +01:00
|
|
|
compress_addr_64(uint8_t bitpos, uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
|
|
|
|
{
|
|
|
|
if(uip_is_addr_mac_addr_based(ipaddr, lladdr)) {
|
2010-05-24 16:28:56 +02:00
|
|
|
return 3 << bitpos; /* 0-bits */
|
2010-11-02 11:56:57 +01:00
|
|
|
} else if(sicslowpan_is_iid_16_bit_compressable(ipaddr)) {
|
2011-03-06 22:34:16 +01:00
|
|
|
/* compress IID to 16 bits xxxx::0000:00ff:fe00:XXXX */
|
2010-03-16 11:21:04 +01:00
|
|
|
memcpy(hc06_ptr, &ipaddr->u16[7], 2);
|
|
|
|
hc06_ptr += 2;
|
2010-05-24 16:28:56 +02:00
|
|
|
return 2 << bitpos; /* 16-bits */
|
2010-03-16 11:21:04 +01:00
|
|
|
} else {
|
|
|
|
/* do not compress IID => xxxx::IID */
|
|
|
|
memcpy(hc06_ptr, &ipaddr->u16[4], 8);
|
|
|
|
hc06_ptr += 8;
|
2010-05-24 16:28:56 +02:00
|
|
|
return 1 << bitpos; /* 64-bits */
|
2010-03-16 11:21:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-31 22:42:27 +02:00
|
|
|
/*-------------------------------------------------------------------- */
|
|
|
|
/* Uncompress addresses based on a prefix and a postfix with zeroes in
|
|
|
|
* between. If the postfix is zero in length it will use the link address
|
|
|
|
* to configure the IP address (autoconf style).
|
|
|
|
* pref_post_count takes a byte where the first nibble specify prefix count
|
|
|
|
* and the second postfix count (NOTE: 15/0xf => 16 bytes copy).
|
|
|
|
*/
|
2010-03-16 11:21:04 +01:00
|
|
|
static void
|
2010-05-31 22:42:27 +02:00
|
|
|
uncompress_addr(uip_ipaddr_t *ipaddr, uint8_t const prefix[],
|
2010-11-02 11:56:57 +01:00
|
|
|
uint8_t pref_post_count, uip_lladdr_t *lladdr)
|
|
|
|
{
|
2010-05-31 22:42:27 +02:00
|
|
|
uint8_t prefcount = pref_post_count >> 4;
|
|
|
|
uint8_t postcount = pref_post_count & 0x0f;
|
|
|
|
/* full nibble 15 => 16 */
|
|
|
|
prefcount = prefcount == 15 ? 16 : prefcount;
|
|
|
|
postcount = postcount == 15 ? 16 : postcount;
|
|
|
|
|
|
|
|
PRINTF("Uncompressing %d + %d => ", prefcount, postcount);
|
|
|
|
|
|
|
|
if(prefcount > 0) {
|
|
|
|
memcpy(ipaddr, prefix, prefcount);
|
|
|
|
}
|
|
|
|
if(prefcount + postcount < 16) {
|
|
|
|
memset(&ipaddr->u8[prefcount], 0, 16 - (prefcount + postcount));
|
|
|
|
}
|
|
|
|
if(postcount > 0) {
|
|
|
|
memcpy(&ipaddr->u8[16 - postcount], hc06_ptr, postcount);
|
2011-03-06 22:34:16 +01:00
|
|
|
if(postcount == 2 && prefcount < 11) {
|
|
|
|
/* 16 bits uncompression => 0000:00ff:fe00:XXXX */
|
|
|
|
ipaddr->u8[11] = 0xff;
|
|
|
|
ipaddr->u8[12] = 0xfe;
|
|
|
|
}
|
2010-05-31 22:42:27 +02:00
|
|
|
hc06_ptr += postcount;
|
2010-11-02 11:56:57 +01:00
|
|
|
} else if (prefcount > 0) {
|
2010-06-06 14:44:12 +02:00
|
|
|
/* no IID based configuration if no prefix and no data => unspec */
|
2010-03-16 11:21:04 +01:00
|
|
|
uip_ds6_set_addr_iid(ipaddr, lladdr);
|
|
|
|
}
|
2010-05-31 22:42:27 +02:00
|
|
|
|
|
|
|
PRINT6ADDR(ipaddr);
|
|
|
|
PRINTF("\n");
|
2010-03-16 11:21:04 +01:00
|
|
|
}
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/**
|
|
|
|
* \brief Compress IP/UDP header
|
2008-10-14 14:26:18 +02:00
|
|
|
*
|
2008-10-14 11:42:33 +02:00
|
|
|
* This function is called by the 6lowpan code to create a compressed
|
2009-03-12 22:58:20 +01:00
|
|
|
* 6lowpan packet in the packetbuf buffer from a full IPv6 packet in the
|
2008-10-14 11:42:33 +02:00
|
|
|
* uip_buf buffer.
|
2008-10-14 14:26:18 +02:00
|
|
|
*
|
|
|
|
*
|
2015-09-14 15:55:26 +02:00
|
|
|
* IPHC (RFC 6282)\n
|
|
|
|
* http://tools.ietf.org/html/
|
2008-10-14 11:42:33 +02:00
|
|
|
*
|
|
|
|
* \note We do not support ISA100_UDP header compression
|
|
|
|
*
|
|
|
|
* For LOWPAN_UDP compression, we either compress both ports or none.
|
|
|
|
* General format with LOWPAN_UDP compression is
|
|
|
|
* \verbatim
|
2010-02-25 16:50:58 +01:00
|
|
|
* 1 2 3
|
|
|
|
* 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
|
2008-10-14 11:42:33 +02:00
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
2010-02-25 16:50:58 +01:00
|
|
|
* |0|1|1|TF |N|HLI|C|S|SAM|M|D|DAM| SCI | DCI | comp. IPv6 hdr|
|
2008-10-14 11:42:33 +02:00
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | compressed IPv6 fields ..... |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | LOWPAN_UDP | non compressed UDP fields ... |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | L4 data ... |
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* \endverbatim
|
|
|
|
* \note The context number 00 is reserved for the link local prefix.
|
|
|
|
* For unicast addresses, if we cannot compress the prefix, we neither
|
|
|
|
* compress the IID.
|
2013-12-13 00:09:44 +01:00
|
|
|
* \param link_destaddr L2 destination address, needed to compress IP
|
2008-10-14 11:42:33 +02:00
|
|
|
* dest
|
|
|
|
*/
|
|
|
|
static void
|
2015-09-14 15:55:26 +02:00
|
|
|
compress_hdr_iphc(linkaddr_t *link_destaddr)
|
2008-10-14 11:42:33 +02:00
|
|
|
{
|
2010-05-24 16:28:56 +02:00
|
|
|
uint8_t tmp, iphc0, iphc1;
|
2010-02-25 16:50:58 +01:00
|
|
|
#if DEBUG
|
2011-10-27 17:13:26 +02:00
|
|
|
{ uint16_t ndx;
|
|
|
|
PRINTF("before compression (%d): ", UIP_IP_BUF->len[1]);
|
|
|
|
for(ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
|
|
|
|
uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
|
|
|
|
PRINTF("%02x", data);
|
|
|
|
}
|
|
|
|
PRINTF("\n");
|
2010-02-25 16:50:58 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
hc06_ptr = packetbuf_ptr + 2;
|
2008-10-14 11:42:33 +02:00
|
|
|
/*
|
|
|
|
* As we copy some bit-length fields, in the IPHC encoding bytes,
|
2008-10-14 14:26:18 +02:00
|
|
|
* we sometimes use |=
|
|
|
|
* If the field is 0, and the current bit value in memory is 1,
|
|
|
|
* this does not work. We therefore reset the IPHC encoding here
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 = SICSLOWPAN_DISPATCH_IPHC;
|
|
|
|
iphc1 = 0;
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_IPHC_BUF[2] = 0; /* might not be used - but needs to be cleared */
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/*
|
2010-02-25 16:50:58 +01:00
|
|
|
* Address handling needs to be made first since it might
|
|
|
|
* cause an extra byte with [ SCI | DCI ]
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* check if dest context exists (for allocating third byte) */
|
|
|
|
/* TODO: fix this so that it remembers the looked up values for
|
|
|
|
avoiding two lookups - or set the lookup values immediately */
|
|
|
|
if(addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr) != NULL ||
|
|
|
|
addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr) != NULL) {
|
|
|
|
/* set context flag and increase hc06_ptr */
|
|
|
|
PRINTF("IPHC: compressing dest or src ipaddr - setting CID\n");
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_CID;
|
2010-02-25 16:50:58 +01:00
|
|
|
hc06_ptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Traffic class, flow label
|
2008-10-14 14:26:18 +02:00
|
|
|
* If flow label is 0, compress it. If traffic class is 0, compress it
|
2008-10-14 11:42:33 +02:00
|
|
|
* We have to process both in the same time as the offset of traffic class
|
2008-10-14 14:26:18 +02:00
|
|
|
* depends on the presence of version and flow label
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2015-10-30 11:41:59 +01:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
tmp = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
|
|
|
|
tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
|
2015-10-30 11:41:59 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
if(((UIP_IP_BUF->tcflow & 0x0F) == 0) &&
|
|
|
|
(UIP_IP_BUF->flow == 0)) {
|
2010-02-25 16:50:58 +01:00
|
|
|
/* flow label can be compressed */
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 |= SICSLOWPAN_IPHC_FL_C;
|
2008-10-14 11:42:33 +02:00
|
|
|
if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
|
|
|
|
((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
|
2008-10-14 14:26:18 +02:00
|
|
|
/* compress (elide) all */
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 |= SICSLOWPAN_IPHC_TC_C;
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
2010-02-25 16:50:58 +01:00
|
|
|
/* compress only the flow label */
|
|
|
|
*hc06_ptr = tmp;
|
|
|
|
hc06_ptr += 1;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
} else {
|
2010-02-25 16:50:58 +01:00
|
|
|
/* Flow label cannot be compressed */
|
2008-10-14 11:42:33 +02:00
|
|
|
if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
|
|
|
|
((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
|
|
|
|
/* compress only traffic class */
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 |= SICSLOWPAN_IPHC_TC_C;
|
2010-02-25 16:50:58 +01:00
|
|
|
*hc06_ptr = (tmp & 0xc0) |
|
2008-10-14 11:42:33 +02:00
|
|
|
(UIP_IP_BUF->tcflow & 0x0F);
|
2010-03-17 13:08:59 +01:00
|
|
|
memcpy(hc06_ptr + 1, &UIP_IP_BUF->flow, 2);
|
2010-02-25 16:50:58 +01:00
|
|
|
hc06_ptr += 3;
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
|
|
|
/* compress nothing */
|
2010-02-25 16:50:58 +01:00
|
|
|
memcpy(hc06_ptr, &UIP_IP_BUF->vtc, 4);
|
|
|
|
/* but replace the top byte with the new ECN | DSCP format*/
|
|
|
|
*hc06_ptr = tmp;
|
|
|
|
hc06_ptr += 4;
|
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Note that the payload length is always compressed */
|
|
|
|
|
|
|
|
/* Next header. We compress it if UDP */
|
2012-02-01 21:06:38 +01:00
|
|
|
#if UIP_CONF_UDP || UIP_CONF_ROUTER
|
2008-10-14 11:42:33 +02:00
|
|
|
if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 |= SICSLOWPAN_IPHC_NH_C;
|
2010-03-17 13:08:59 +01:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
#endif /*UIP_CONF_UDP*/
|
2015-09-14 15:55:26 +02:00
|
|
|
|
2010-05-24 16:28:56 +02:00
|
|
|
if ((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
|
2010-02-25 16:50:58 +01:00
|
|
|
*hc06_ptr = UIP_IP_BUF->proto;
|
|
|
|
hc06_ptr += 1;
|
2010-03-17 13:08:59 +01:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/*
|
2008-10-14 14:26:18 +02:00
|
|
|
* Hop limit
|
2008-10-14 11:42:33 +02:00
|
|
|
* if 1: compress, encoding is 01
|
|
|
|
* if 64: compress, encoding is 10
|
|
|
|
* if 255: compress, encoding is 11
|
|
|
|
* else do not compress
|
|
|
|
*/
|
|
|
|
switch(UIP_IP_BUF->ttl) {
|
|
|
|
case 1:
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 |= SICSLOWPAN_IPHC_TTL_1;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
case 64:
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 |= SICSLOWPAN_IPHC_TTL_64;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
case 255:
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 |= SICSLOWPAN_IPHC_TTL_255;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
default:
|
2010-02-25 16:50:58 +01:00
|
|
|
*hc06_ptr = UIP_IP_BUF->ttl;
|
|
|
|
hc06_ptr += 1;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-10-14 14:26:18 +02:00
|
|
|
/* source address - cannot be multicast */
|
2010-02-25 16:50:58 +01:00
|
|
|
if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
|
|
|
|
PRINTF("IPHC: compressing unspecified - setting SAC\n");
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_SAC;
|
|
|
|
iphc1 |= SICSLOWPAN_IPHC_SAM_00;
|
2010-02-25 16:50:58 +01:00
|
|
|
} else if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr))
|
2008-10-14 11:42:33 +02:00
|
|
|
!= NULL) {
|
2010-02-25 16:50:58 +01:00
|
|
|
/* elide the prefix - indicate by CID and set context + SAC */
|
|
|
|
PRINTF("IPHC: compressing src with context - setting CID & SAC ctx: %d\n",
|
2015-10-30 11:41:59 +01:00
|
|
|
context->number);
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_IPHC_BUF[2] |= context->number << 4;
|
2010-02-25 16:50:58 +01:00
|
|
|
/* compession compare with this nodes address (source) */
|
2010-03-16 11:21:04 +01:00
|
|
|
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
|
|
|
|
&UIP_IP_BUF->srcipaddr, &uip_lladdr);
|
2010-02-25 16:50:58 +01:00
|
|
|
/* No context found for this address */
|
2015-10-20 11:18:46 +02:00
|
|
|
} else if(uip_is_addr_linklocal(&UIP_IP_BUF->srcipaddr) &&
|
2015-10-30 11:41:59 +01:00
|
|
|
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
|
|
|
|
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
|
|
|
|
UIP_IP_BUF->destipaddr.u16[3] == 0) {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
|
|
|
|
&UIP_IP_BUF->srcipaddr, &uip_lladdr);
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
2010-02-25 16:50:58 +01:00
|
|
|
/* send the full address => SAC = 0, SAM = 00 */
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_SAM_00; /* 128-bits */
|
2010-02-25 16:50:58 +01:00
|
|
|
memcpy(hc06_ptr, &UIP_IP_BUF->srcipaddr.u16[0], 16);
|
|
|
|
hc06_ptr += 16;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* dest address*/
|
|
|
|
if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
|
|
|
|
/* Address is multicast, try to compress */
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_M;
|
2010-02-25 16:50:58 +01:00
|
|
|
if(sicslowpan_is_mcast_addr_compressable8(&UIP_IP_BUF->destipaddr)) {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_DAM_11;
|
2010-02-25 16:50:58 +01:00
|
|
|
/* use last byte */
|
|
|
|
*hc06_ptr = UIP_IP_BUF->destipaddr.u8[15];
|
|
|
|
hc06_ptr += 1;
|
2010-11-02 11:56:57 +01:00
|
|
|
} else if(sicslowpan_is_mcast_addr_compressable32(&UIP_IP_BUF->destipaddr)) {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_DAM_10;
|
2010-02-25 16:50:58 +01:00
|
|
|
/* second byte + the last three */
|
|
|
|
*hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
|
|
|
|
memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[13], 3);
|
|
|
|
hc06_ptr += 4;
|
2010-11-02 11:56:57 +01:00
|
|
|
} else if(sicslowpan_is_mcast_addr_compressable48(&UIP_IP_BUF->destipaddr)) {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_DAM_01;
|
2010-02-25 16:50:58 +01:00
|
|
|
/* second byte + the last five */
|
|
|
|
*hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
|
|
|
|
memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[11], 5);
|
|
|
|
hc06_ptr += 6;
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_DAM_00;
|
2010-02-25 16:50:58 +01:00
|
|
|
/* full address */
|
|
|
|
memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u8[0], 16);
|
|
|
|
hc06_ptr += 16;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Address is unicast, try to compress */
|
|
|
|
if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr)) != NULL) {
|
|
|
|
/* elide the prefix */
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_DAC;
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_IPHC_BUF[2] |= context->number;
|
2010-02-25 16:50:58 +01:00
|
|
|
/* compession compare with link adress (destination) */
|
2010-03-16 11:21:04 +01:00
|
|
|
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
|
2015-10-30 11:41:59 +01:00
|
|
|
&UIP_IP_BUF->destipaddr,
|
|
|
|
(uip_lladdr_t *)link_destaddr);
|
2010-02-25 16:50:58 +01:00
|
|
|
/* No context found for this address */
|
2015-10-20 11:18:46 +02:00
|
|
|
} else if(uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) &&
|
2015-10-30 11:41:59 +01:00
|
|
|
UIP_IP_BUF->destipaddr.u16[1] == 0 &&
|
|
|
|
UIP_IP_BUF->destipaddr.u16[2] == 0 &&
|
|
|
|
UIP_IP_BUF->destipaddr.u16[3] == 0) {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
|
2013-12-13 00:09:44 +01:00
|
|
|
&UIP_IP_BUF->destipaddr, (uip_lladdr_t *)link_destaddr);
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
|
|
|
/* send the full address */
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= SICSLOWPAN_IPHC_DAM_00; /* 128-bits */
|
2010-02-25 16:50:58 +01:00
|
|
|
memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u16[0], 16);
|
|
|
|
hc06_ptr += 16;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
}
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
uncomp_hdr_len = UIP_IPH_LEN;
|
|
|
|
|
2012-02-01 21:06:38 +01:00
|
|
|
#if UIP_CONF_UDP || UIP_CONF_ROUTER
|
2008-10-14 11:42:33 +02:00
|
|
|
/* UDP header compression */
|
|
|
|
if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
|
2010-03-26 11:28:51 +01:00
|
|
|
PRINTF("IPHC: Uncompressed UDP ports on send side: %x, %x\n",
|
2015-10-30 11:41:59 +01:00
|
|
|
UIP_HTONS(UIP_UDP_BUF->srcport), UIP_HTONS(UIP_UDP_BUF->destport));
|
2010-03-26 11:28:51 +01:00
|
|
|
/* Mask out the last 4 bits can be used as a mask */
|
2010-10-19 20:29:03 +02:00
|
|
|
if(((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
|
|
|
|
((UIP_HTONS(UIP_UDP_BUF->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
|
2010-03-26 11:28:51 +01:00
|
|
|
/* we can compress 12 bits of both source and dest */
|
|
|
|
*hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_11;
|
|
|
|
PRINTF("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
|
|
|
|
*(hc06_ptr + 1) =
|
2015-10-30 11:41:59 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
|
|
|
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
|
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
|
|
|
|
SICSLOWPAN_UDP_4_BIT_PORT_MIN));
|
2010-03-26 11:28:51 +01:00
|
|
|
hc06_ptr += 2;
|
2010-10-19 20:29:03 +02:00
|
|
|
} else if((UIP_HTONS(UIP_UDP_BUF->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
|
2010-03-26 11:28:51 +01:00
|
|
|
/* we can compress 8 bits of dest, leave source. */
|
|
|
|
*hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_01;
|
|
|
|
PRINTF("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
|
|
|
|
memcpy(hc06_ptr + 1, &UIP_UDP_BUF->srcport, 2);
|
|
|
|
*(hc06_ptr + 3) =
|
2015-10-30 11:41:59 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
|
|
|
|
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
2010-03-26 11:28:51 +01:00
|
|
|
hc06_ptr += 4;
|
2010-10-19 20:29:03 +02:00
|
|
|
} else if((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
|
2010-03-26 11:28:51 +01:00
|
|
|
/* we can compress 8 bits of src, leave dest. Copy compressed port */
|
|
|
|
*hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_10;
|
|
|
|
PRINTF("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *hc06_ptr);
|
2010-02-25 16:50:58 +01:00
|
|
|
*(hc06_ptr + 1) =
|
2015-10-30 11:41:59 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
|
|
|
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
2010-03-26 11:28:51 +01:00
|
|
|
memcpy(hc06_ptr + 2, &UIP_UDP_BUF->destport, 2);
|
2010-02-25 16:50:58 +01:00
|
|
|
hc06_ptr += 4;
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
2010-03-26 11:28:51 +01:00
|
|
|
/* we cannot compress. Copy uncompressed ports, full checksum */
|
|
|
|
*hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_00;
|
|
|
|
PRINTF("IPHC: cannot compress headers\n");
|
2010-02-25 16:50:58 +01:00
|
|
|
memcpy(hc06_ptr + 1, &UIP_UDP_BUF->srcport, 4);
|
2010-03-26 11:28:51 +01:00
|
|
|
hc06_ptr += 5;
|
|
|
|
}
|
|
|
|
/* always inline the checksum */
|
|
|
|
if(1) {
|
|
|
|
memcpy(hc06_ptr, &UIP_UDP_BUF->udpchksum, 2);
|
|
|
|
hc06_ptr += 2;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
uncomp_hdr_len += UIP_UDPH_LEN;
|
|
|
|
}
|
2008-10-14 14:26:18 +02:00
|
|
|
#endif /*UIP_CONF_UDP*/
|
2010-05-24 16:28:56 +02:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
/* before the packetbuf_hdr_len operation */
|
|
|
|
PACKETBUF_IPHC_BUF[0] = iphc0;
|
|
|
|
PACKETBUF_IPHC_BUF[1] = iphc1;
|
2010-05-24 16:28:56 +02:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
|
2008-10-14 11:42:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/**
|
2015-09-14 15:55:26 +02:00
|
|
|
* \brief Uncompress IPHC (i.e., IPHC and LOWPAN_UDP) headers and put
|
2008-10-14 11:42:33 +02:00
|
|
|
* them in sicslowpan_buf
|
|
|
|
*
|
|
|
|
* This function is called by the input function when the dispatch is
|
2015-09-14 15:55:26 +02:00
|
|
|
* IPHC.
|
2013-12-13 00:09:44 +01:00
|
|
|
* We %process the packet in the packetbuf buffer, uncompress the header
|
2008-10-14 11:42:33 +02:00
|
|
|
* fields, and copy the result in the sicslowpan buffer.
|
2013-12-13 00:09:44 +01:00
|
|
|
* At the end of the decompression, packetbuf_hdr_len and uncompressed_hdr_len
|
2008-10-14 11:42:33 +02:00
|
|
|
* are set to the appropriate values
|
|
|
|
*
|
2015-09-18 14:22:17 +02:00
|
|
|
* \param buf Pointer to the buffer to uncompress the packet into.
|
2008-10-14 11:42:33 +02:00
|
|
|
* \param ip_len Equal to 0 if the packet is not a fragment (IP length
|
|
|
|
* is then inferred from the L2 length), non 0 if the packet is a 1st
|
|
|
|
* fragment.
|
|
|
|
*/
|
|
|
|
static void
|
2015-09-14 15:55:26 +02:00
|
|
|
uncompress_hdr_iphc(uint8_t *buf, uint16_t ip_len)
|
2010-11-02 11:56:57 +01:00
|
|
|
{
|
2010-05-24 16:28:56 +02:00
|
|
|
uint8_t tmp, iphc0, iphc1;
|
2010-02-25 16:50:58 +01:00
|
|
|
/* at least two byte will be used for the encoding */
|
2013-12-13 00:09:44 +01:00
|
|
|
hc06_ptr = packetbuf_ptr + packetbuf_hdr_len + 2;
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
iphc0 = PACKETBUF_IPHC_BUF[0];
|
|
|
|
iphc1 = PACKETBUF_IPHC_BUF[1];
|
2010-05-24 16:28:56 +02:00
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
/* another if the CID flag is set */
|
2010-05-24 16:28:56 +02:00
|
|
|
if(iphc1 & SICSLOWPAN_IPHC_CID) {
|
2010-02-25 16:50:58 +01:00
|
|
|
PRINTF("IPHC: CID flag set - increase header with one\n");
|
|
|
|
hc06_ptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Traffic class and flow label */
|
2010-05-24 16:28:56 +02:00
|
|
|
if((iphc0 & SICSLOWPAN_IPHC_FL_C) == 0) {
|
2010-03-09 17:19:44 +01:00
|
|
|
/* Flow label are carried inline */
|
2010-05-24 16:28:56 +02:00
|
|
|
if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
|
2010-03-09 17:19:44 +01:00
|
|
|
/* Traffic class is carried inline */
|
2015-09-14 15:55:26 +02:00
|
|
|
memcpy(&SICSLOWPAN_IP_BUF(buf)->tcflow, hc06_ptr + 1, 3);
|
2010-03-09 17:19:44 +01:00
|
|
|
tmp = *hc06_ptr;
|
|
|
|
hc06_ptr += 4;
|
2015-09-14 15:55:26 +02:00
|
|
|
/* IPHC format of tc is ECN | DSCP , original is DSCP | ECN */
|
2010-03-09 17:19:44 +01:00
|
|
|
/* set version, pick highest DSCP bits and set in vtc */
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((tmp >> 2) & 0x0f);
|
2010-03-09 17:19:44 +01:00
|
|
|
/* ECN rolled down two steps + lowest DSCP bits at top two bits */
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
|
|
|
|
(SICSLOWPAN_IP_BUF(buf)->tcflow & 0x0f);
|
2010-03-09 17:19:44 +01:00
|
|
|
} else {
|
|
|
|
/* Traffic class is compressed (set version and no TC)*/
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
|
2010-03-09 17:19:44 +01:00
|
|
|
/* highest flow label bits + ECN bits */
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->tcflow = (*hc06_ptr & 0x0F) |
|
|
|
|
((*hc06_ptr >> 2) & 0x30);
|
|
|
|
memcpy(&SICSLOWPAN_IP_BUF(buf)->flow, hc06_ptr + 1, 2);
|
2010-03-09 17:19:44 +01:00
|
|
|
hc06_ptr += 3;
|
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
2010-03-09 17:19:44 +01:00
|
|
|
/* Version is always 6! */
|
|
|
|
/* Version and flow label are compressed */
|
2010-05-24 16:28:56 +02:00
|
|
|
if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
|
2010-03-09 17:19:44 +01:00
|
|
|
/* Traffic class is inline */
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->vtc = 0x60 | ((*hc06_ptr >> 2) & 0x0f);
|
|
|
|
SICSLOWPAN_IP_BUF(buf)->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30);
|
|
|
|
SICSLOWPAN_IP_BUF(buf)->flow = 0;
|
2011-05-09 09:57:37 +02:00
|
|
|
hc06_ptr += 1;
|
2010-03-09 17:19:44 +01:00
|
|
|
} else {
|
|
|
|
/* Traffic class is compressed */
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->vtc = 0x60;
|
|
|
|
SICSLOWPAN_IP_BUF(buf)->tcflow = 0;
|
|
|
|
SICSLOWPAN_IP_BUF(buf)->flow = 0;
|
2010-03-09 17:19:44 +01:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/* Next Header */
|
2010-05-24 16:28:56 +02:00
|
|
|
if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
|
2008-10-14 11:42:33 +02:00
|
|
|
/* Next header is carried inline */
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->proto = *hc06_ptr;
|
|
|
|
PRINTF("IPHC: next header inline: %d\n", SICSLOWPAN_IP_BUF(buf)->proto);
|
2010-02-25 16:50:58 +01:00
|
|
|
hc06_ptr += 1;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Hop limit */
|
2010-05-31 22:42:27 +02:00
|
|
|
if((iphc0 & 0x03) != SICSLOWPAN_IPHC_TTL_I) {
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->ttl = ttl_values[iphc0 & 0x03];
|
2010-05-31 22:42:27 +02:00
|
|
|
} else {
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->ttl = *hc06_ptr;
|
2010-05-31 22:42:27 +02:00
|
|
|
hc06_ptr += 1;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
|
2010-05-31 22:42:27 +02:00
|
|
|
/* put the source address compression mode SAM in the tmp var */
|
|
|
|
tmp = ((iphc1 & SICSLOWPAN_IPHC_SAM_11) >> SICSLOWPAN_IPHC_SAM_BIT) & 0x03;
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
/* context based compression */
|
2010-05-24 16:28:56 +02:00
|
|
|
if(iphc1 & SICSLOWPAN_IPHC_SAC) {
|
|
|
|
uint8_t sci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_IPHC_BUF[2] >> 4 : 0;
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2010-09-23 21:57:50 +02:00
|
|
|
/* Source address - check context != NULL only if SAM bits are != 0*/
|
|
|
|
if (tmp != 0) {
|
|
|
|
context = addr_context_lookup_by_number(sci);
|
2008-10-14 11:42:33 +02:00
|
|
|
if(context == NULL) {
|
|
|
|
PRINTF("sicslowpan uncompress_hdr: error context not found\n");
|
|
|
|
return;
|
|
|
|
}
|
2010-02-25 16:50:58 +01:00
|
|
|
}
|
2010-09-23 21:57:50 +02:00
|
|
|
/* if tmp == 0 we do not have a context and therefore no prefix */
|
2015-09-14 15:55:26 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr,
|
2010-09-23 21:57:50 +02:00
|
|
|
tmp != 0 ? context->prefix : NULL, unc_ctxconf[tmp],
|
2010-05-31 22:42:27 +02:00
|
|
|
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
2010-02-25 16:50:58 +01:00
|
|
|
} else {
|
|
|
|
/* no compression and link local */
|
2015-09-14 15:55:26 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->srcipaddr, llprefix, unc_llconf[tmp],
|
2010-05-31 22:42:27 +02:00
|
|
|
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Destination address */
|
2010-05-31 22:42:27 +02:00
|
|
|
/* put the destination address compression mode into tmp */
|
|
|
|
tmp = ((iphc1 & SICSLOWPAN_IPHC_DAM_11) >> SICSLOWPAN_IPHC_DAM_BIT) & 0x03;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
/* multicast compression */
|
2010-05-24 16:28:56 +02:00
|
|
|
if(iphc1 & SICSLOWPAN_IPHC_M) {
|
2010-02-25 16:50:58 +01:00
|
|
|
/* context based multicast compression */
|
2010-05-24 16:28:56 +02:00
|
|
|
if(iphc1 & SICSLOWPAN_IPHC_DAC) {
|
2010-02-25 16:50:58 +01:00
|
|
|
/* TODO: implement this */
|
|
|
|
} else {
|
2010-05-31 22:42:27 +02:00
|
|
|
/* non-context based multicast compression - */
|
|
|
|
/* DAM_00: 128 bits */
|
|
|
|
/* DAM_01: 48 bits FFXX::00XX:XXXX:XXXX */
|
|
|
|
/* DAM_10: 32 bits FFXX::00XX:XXXX */
|
|
|
|
/* DAM_11: 8 bits FF02::00XX */
|
|
|
|
uint8_t prefix[] = {0xff, 0x02};
|
|
|
|
if(tmp > 0 && tmp < 3) {
|
|
|
|
prefix[1] = *hc06_ptr;
|
|
|
|
hc06_ptr++;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2010-05-31 22:42:27 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, prefix,
|
2010-05-31 22:42:27 +02:00
|
|
|
unc_mxconf[tmp], NULL);
|
2010-02-25 16:50:58 +01:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* no multicast */
|
|
|
|
/* Context based */
|
2010-05-24 16:28:56 +02:00
|
|
|
if(iphc1 & SICSLOWPAN_IPHC_DAC) {
|
2015-10-30 11:41:59 +01:00
|
|
|
uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ? PACKETBUF_IPHC_BUF[2] & 0x0f : 0;
|
2010-02-25 16:50:58 +01:00
|
|
|
context = addr_context_lookup_by_number(dci);
|
|
|
|
|
|
|
|
/* all valid cases below need the context! */
|
2008-10-14 11:42:33 +02:00
|
|
|
if(context == NULL) {
|
2015-10-30 11:41:59 +01:00
|
|
|
PRINTF("sicslowpan uncompress_hdr: error context not found\n");
|
|
|
|
return;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2015-09-14 15:55:26 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, context->prefix,
|
2010-05-31 22:42:27 +02:00
|
|
|
unc_ctxconf[tmp],
|
|
|
|
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
2010-02-25 16:50:58 +01:00
|
|
|
} else {
|
|
|
|
/* not context based => link local M = 0, DAC = 0 - same as SAC */
|
2015-09-14 15:55:26 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF(buf)->destipaddr, llprefix,
|
2010-05-31 22:42:27 +02:00
|
|
|
unc_llconf[tmp],
|
|
|
|
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
2010-02-25 16:50:58 +01:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
uncomp_hdr_len += UIP_IPH_LEN;
|
|
|
|
|
2008-10-14 14:26:18 +02:00
|
|
|
/* Next header processing - continued */
|
2010-05-24 16:28:56 +02:00
|
|
|
if((iphc0 & SICSLOWPAN_IPHC_NH_C)) {
|
2008-10-14 11:42:33 +02:00
|
|
|
/* The next header is compressed, NHC is following */
|
2010-03-17 13:08:59 +01:00
|
|
|
if((*hc06_ptr & SICSLOWPAN_NHC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) {
|
2010-03-26 11:28:51 +01:00
|
|
|
uint8_t checksum_compressed;
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->proto = UIP_PROTO_UDP;
|
2010-03-26 11:28:51 +01:00
|
|
|
checksum_compressed = *hc06_ptr & SICSLOWPAN_NHC_UDP_CHECKSUMC;
|
|
|
|
PRINTF("IPHC: Incoming header value: %i\n", *hc06_ptr);
|
|
|
|
switch(*hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
|
|
|
|
case SICSLOWPAN_NHC_UDP_CS_P_00:
|
2015-09-14 15:55:26 +02:00
|
|
|
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF(buf)->srcport, hc06_ptr + 1, 2);
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF(buf)->destport, hc06_ptr + 3, 2);
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n",
|
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->srcport),
|
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->destport));
|
|
|
|
hc06_ptr += 5;
|
|
|
|
break;
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2010-03-26 11:28:51 +01:00
|
|
|
case SICSLOWPAN_NHC_UDP_CS_P_01:
|
2010-05-31 22:42:27 +02:00
|
|
|
/* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
|
2015-09-14 15:55:26 +02:00
|
|
|
PRINTF("IPHC: Decompressing destination\n");
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF(buf)->srcport, hc06_ptr + 1, 2);
|
|
|
|
SICSLOWPAN_UDP_BUF(buf)->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->destport));
|
|
|
|
hc06_ptr += 4;
|
|
|
|
break;
|
2010-03-26 11:28:51 +01:00
|
|
|
|
|
|
|
case SICSLOWPAN_NHC_UDP_CS_P_10:
|
2010-05-31 22:42:27 +02:00
|
|
|
/* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit inline*/
|
2015-09-14 15:55:26 +02:00
|
|
|
PRINTF("IPHC: Decompressing source\n");
|
|
|
|
SICSLOWPAN_UDP_BUF(buf)->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
|
|
|
|
(*(hc06_ptr + 1)));
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF(buf)->destport, hc06_ptr + 2, 2);
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->destport));
|
|
|
|
hc06_ptr += 4;
|
|
|
|
break;
|
2010-03-26 11:28:51 +01:00
|
|
|
|
|
|
|
case SICSLOWPAN_NHC_UDP_CS_P_11:
|
2015-09-14 15:55:26 +02:00
|
|
|
/* 1 byte for NHC, 1 byte for ports */
|
|
|
|
SICSLOWPAN_UDP_BUF(buf)->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
|
|
|
(*(hc06_ptr + 1) >> 4));
|
|
|
|
SICSLOWPAN_UDP_BUF(buf)->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
|
|
|
((*(hc06_ptr + 1)) & 0x0F));
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
|
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF(buf)->destport));
|
|
|
|
hc06_ptr += 2;
|
|
|
|
break;
|
2010-03-26 11:28:51 +01:00
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
default:
|
2015-10-30 11:41:59 +01:00
|
|
|
PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n");
|
|
|
|
return;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2010-03-26 11:28:51 +01:00
|
|
|
if(!checksum_compressed) { /* has_checksum, default */
|
2015-09-14 15:55:26 +02:00
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF(buf)->udpchksum, hc06_ptr, 2);
|
|
|
|
hc06_ptr += 2;
|
|
|
|
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum included\n");
|
2010-03-26 11:28:51 +01:00
|
|
|
} else {
|
2015-10-30 11:41:59 +01:00
|
|
|
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum *NOT* included\n");
|
2010-03-26 11:28:51 +01:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
uncomp_hdr_len += UIP_UDPH_LEN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len = hc06_ptr - packetbuf_ptr;
|
2015-10-30 11:41:59 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/* IP length field. */
|
|
|
|
if(ip_len == 0) {
|
2013-12-13 00:09:44 +01:00
|
|
|
int len = packetbuf_datalen() - packetbuf_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
/* This is not a fragmented packet */
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->len[0] = len >> 8;
|
|
|
|
SICSLOWPAN_IP_BUF(buf)->len[1] = len & 0x00FF;
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
|
|
|
/* This is a 1st fragment */
|
2015-09-14 15:55:26 +02:00
|
|
|
SICSLOWPAN_IP_BUF(buf)->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
|
|
|
|
SICSLOWPAN_IP_BUF(buf)->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2015-10-30 11:41:59 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/* length field in UDP header */
|
2015-09-14 15:55:26 +02:00
|
|
|
if(SICSLOWPAN_IP_BUF(buf)->proto == UIP_PROTO_UDP) {
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF(buf)->udplen, &SICSLOWPAN_IP_BUF(buf)->len[0], 2);
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/** @} */
|
2010-02-25 16:50:58 +01:00
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
2008-10-14 14:26:18 +02:00
|
|
|
/** \name IPv6 dispatch "compression" function
|
2008-10-14 11:42:33 +02:00
|
|
|
* @{ */
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/* \brief Packets "Compression" when only IPv6 dispatch is used
|
2008-10-14 14:26:18 +02:00
|
|
|
*
|
|
|
|
* There is no compression in this case, all fields are sent
|
2008-10-14 11:42:33 +02:00
|
|
|
* inline. We just add the IPv6 dispatch byte before the packet.
|
|
|
|
* \verbatim
|
|
|
|
* 0 1 2 3
|
|
|
|
* 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
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | IPv6 Dsp | IPv6 header and payload ...
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* \endverbatim
|
|
|
|
*/
|
|
|
|
static void
|
2013-12-13 00:09:44 +01:00
|
|
|
compress_hdr_ipv6(linkaddr_t *link_destaddr)
|
2010-11-02 11:56:57 +01:00
|
|
|
{
|
2013-12-13 00:09:44 +01:00
|
|
|
*packetbuf_ptr = SICSLOWPAN_DISPATCH_IPV6;
|
|
|
|
packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
|
|
|
|
memcpy(packetbuf_ptr + packetbuf_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
|
|
|
|
packetbuf_hdr_len += UIP_IPH_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
uncomp_hdr_len += UIP_IPH_LEN;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
2008-10-14 14:26:18 +02:00
|
|
|
/** \name Input/output functions common to all compression schemes
|
2008-10-14 11:42:33 +02:00
|
|
|
* @{ */
|
|
|
|
/*--------------------------------------------------------------------*/
|
2010-03-29 13:48:09 +02:00
|
|
|
/**
|
|
|
|
* Callback function for the MAC packet sent callback
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
packet_sent(void *ptr, int status, int transmissions)
|
|
|
|
{
|
2013-07-29 21:50:33 +02:00
|
|
|
uip_ds6_link_neighbor_callback(status, transmissions);
|
|
|
|
|
2011-10-20 12:37:56 +02:00
|
|
|
if(callback != NULL) {
|
|
|
|
callback->output_callback(status);
|
|
|
|
}
|
2012-03-26 23:37:17 +02:00
|
|
|
last_tx_status = status;
|
2010-03-29 13:48:09 +02:00
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
2008-10-14 11:42:33 +02:00
|
|
|
/**
|
|
|
|
* \brief This function is called by the 6lowpan code to send out a
|
|
|
|
* packet.
|
|
|
|
* \param dest the link layer destination address of the packet
|
|
|
|
*/
|
|
|
|
static void
|
2013-12-12 23:58:52 +01:00
|
|
|
send_packet(linkaddr_t *dest)
|
2008-10-14 11:42:33 +02:00
|
|
|
{
|
|
|
|
/* Set the link layer destination address for the packet as a
|
2009-03-12 22:58:20 +01:00
|
|
|
* packetbuf attribute. The MAC layer can access the destination
|
2009-04-06 15:11:20 +02:00
|
|
|
* address with the function packetbuf_addr(PACKETBUF_ADDR_RECEIVER).
|
2008-10-14 14:26:18 +02:00
|
|
|
*/
|
2009-03-12 22:58:20 +01:00
|
|
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest);
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2011-03-21 22:25:55 +01:00
|
|
|
#if NETSTACK_CONF_BRIDGE_MODE
|
|
|
|
/* This needs to be explicitly set here for bridge mode to work */
|
|
|
|
packetbuf_set_addr(PACKETBUF_ADDR_SENDER,(void*)&uip_lladdr);
|
|
|
|
#endif
|
|
|
|
|
2010-03-12 14:20:13 +01:00
|
|
|
/* Provide a callback function to receive the result of
|
|
|
|
a packet transmission. */
|
2013-05-24 09:21:53 +02:00
|
|
|
NETSTACK_LLSEC.send(&packet_sent, NULL);
|
2010-02-06 08:49:58 +01:00
|
|
|
|
|
|
|
/* If we are sending multiple packets in a row, we need to let the
|
|
|
|
watchdog know that we are still alive. */
|
|
|
|
watchdog_periodic();
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2011-09-02 13:51:09 +02:00
|
|
|
/*--------------------------------------------------------------------*/
|
2008-10-14 11:42:33 +02:00
|
|
|
/** \brief Take an IP packet and format it to be sent on an 802.15.4
|
|
|
|
* network using 6lowpan.
|
|
|
|
* \param localdest The MAC address of the destination
|
|
|
|
*
|
|
|
|
* The IP packet is initially in uip_buf. Its header is compressed
|
|
|
|
* and if necessary it is fragmented. The resulting
|
2009-03-12 22:58:20 +01:00
|
|
|
* packet/fragments are put in packetbuf and delivered to the 802.15.4
|
2008-10-14 11:42:33 +02:00
|
|
|
* MAC.
|
|
|
|
*/
|
2011-01-04 21:22:21 +01:00
|
|
|
static uint8_t
|
2013-11-16 14:42:57 +01:00
|
|
|
output(const uip_lladdr_t *localdest)
|
2008-10-14 11:42:33 +02:00
|
|
|
{
|
2013-03-17 23:55:01 +01:00
|
|
|
int framer_hdrlen;
|
2015-09-18 14:22:17 +02:00
|
|
|
int max_payload;
|
2013-03-17 23:55:01 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/* The MAC address of the destination of the packet */
|
2013-12-12 23:58:52 +01:00
|
|
|
linkaddr_t dest;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-11-11 11:44:42 +01:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
2012-03-26 23:19:02 +02:00
|
|
|
/* Number of bytes processed. */
|
|
|
|
uint16_t processed_ip_out_len;
|
2015-11-11 11:44:42 +01:00
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
2012-03-26 23:19:02 +02:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/* init */
|
|
|
|
uncomp_hdr_len = 0;
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len = 0;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
/* reset packetbuf buffer */
|
2009-03-12 22:58:20 +01:00
|
|
|
packetbuf_clear();
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_ptr = packetbuf_dataptr();
|
2009-11-02 12:58:56 +01:00
|
|
|
|
2010-10-26 15:25:32 +02:00
|
|
|
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
|
|
|
|
SICSLOWPAN_MAX_MAC_TRANSMISSIONS);
|
2010-04-01 12:01:01 +02:00
|
|
|
|
2011-10-20 12:37:56 +02:00
|
|
|
if(callback) {
|
|
|
|
/* call the attribution when the callback comes, but set attributes
|
|
|
|
here ! */
|
|
|
|
set_packet_attrs();
|
|
|
|
}
|
|
|
|
|
2015-05-06 14:34:29 +02:00
|
|
|
#if PACKETBUF_WITH_PACKET_TYPE
|
2010-04-01 12:56:00 +02:00
|
|
|
#define TCP_FIN 0x01
|
2011-02-10 22:47:45 +01:00
|
|
|
#define TCP_ACK 0x10
|
|
|
|
#define TCP_CTL 0x3f
|
2010-04-01 12:01:01 +02:00
|
|
|
/* Set stream mode for all TCP packets, except FIN packets. */
|
|
|
|
if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
|
2011-02-10 22:47:45 +01:00
|
|
|
(UIP_TCP_BUF->flags & TCP_FIN) == 0 &&
|
|
|
|
(UIP_TCP_BUF->flags & TCP_CTL) != TCP_ACK) {
|
2010-04-01 12:01:01 +02:00
|
|
|
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
|
|
|
|
PACKETBUF_ATTR_PACKET_TYPE_STREAM);
|
2011-02-10 22:47:45 +01:00
|
|
|
} else if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
|
|
|
|
(UIP_TCP_BUF->flags & TCP_FIN) == TCP_FIN) {
|
|
|
|
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
|
|
|
|
PACKETBUF_ATTR_PACKET_TYPE_STREAM_END);
|
2009-11-02 12:58:56 +01:00
|
|
|
}
|
2015-05-06 14:34:29 +02:00
|
|
|
#endif
|
2011-02-10 22:47:45 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/*
|
|
|
|
* The destination address will be tagged to each outbound
|
|
|
|
* packet. If the argument localdest is NULL, we are sending a
|
2008-10-14 14:26:18 +02:00
|
|
|
* broadcast packet.
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
|
|
|
if(localdest == NULL) {
|
2013-12-12 23:58:52 +01:00
|
|
|
linkaddr_copy(&dest, &linkaddr_null);
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
2013-12-12 23:58:52 +01:00
|
|
|
linkaddr_copy(&dest, (const linkaddr_t *)localdest);
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2015-10-30 11:41:59 +01:00
|
|
|
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("sicslowpan output: sending packet len %d\n", uip_len);
|
2011-09-02 13:51:09 +02:00
|
|
|
|
|
|
|
if(uip_len >= COMPRESSION_THRESHOLD) {
|
|
|
|
/* Try to compress the headers */
|
2010-02-25 16:50:58 +01:00
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
|
2011-09-02 13:51:09 +02:00
|
|
|
compress_hdr_ipv6(&dest);
|
2010-02-25 16:50:58 +01:00
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
|
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
|
2015-09-14 15:55:26 +02:00
|
|
|
compress_hdr_iphc(&dest);
|
2010-02-25 16:50:58 +01:00
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
|
2011-09-02 13:51:09 +02:00
|
|
|
} else {
|
|
|
|
compress_hdr_ipv6(&dest);
|
|
|
|
}
|
2013-12-13 00:09:44 +01:00
|
|
|
PRINTFO("sicslowpan output: header of len %d\n", packetbuf_hdr_len);
|
2011-09-02 13:51:09 +02:00
|
|
|
|
2013-03-17 23:55:01 +01:00
|
|
|
/* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_RDC.
|
|
|
|
* We calculate it here only to make a better decision of whether the outgoing packet
|
|
|
|
* needs to be fragmented or not. */
|
|
|
|
#define USE_FRAMER_HDRLEN 1
|
|
|
|
#if USE_FRAMER_HDRLEN
|
|
|
|
packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
|
2014-04-11 17:03:23 +02:00
|
|
|
framer_hdrlen = NETSTACK_FRAMER.length();
|
2013-03-17 23:55:01 +01:00
|
|
|
if(framer_hdrlen < 0) {
|
|
|
|
/* Framing failed, we assume the maximum header length */
|
2015-09-18 14:22:17 +02:00
|
|
|
framer_hdrlen = 21;
|
2013-03-17 23:55:01 +01:00
|
|
|
}
|
|
|
|
#else /* USE_FRAMER_HDRLEN */
|
2015-09-18 14:22:17 +02:00
|
|
|
framer_hdrlen = 21;
|
2013-03-17 23:55:01 +01:00
|
|
|
#endif /* USE_FRAMER_HDRLEN */
|
|
|
|
|
2015-09-18 14:22:17 +02:00
|
|
|
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
|
|
|
|
if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) {
|
2008-10-14 11:42:33 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
2010-02-06 10:42:49 +01:00
|
|
|
struct queuebuf *q;
|
2015-09-14 15:55:26 +02:00
|
|
|
uint16_t frag_tag;
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/*
|
|
|
|
* The outbound IPv6 packet is too large to fit into a single 15.4
|
2008-10-14 14:26:18 +02:00
|
|
|
* packet, so we fragment it into multiple packets and send them.
|
|
|
|
* The first fragment contains frag1 dispatch, then
|
2015-09-14 15:55:26 +02:00
|
|
|
* IPv6/IPHC/HC_UDP dispatchs/headers.
|
2008-10-14 11:42:33 +02:00
|
|
|
* The following fragments contain only the fragn dispatch.
|
|
|
|
*/
|
2015-06-12 16:02:50 +02:00
|
|
|
int estimated_fragments = ((int)uip_len) / (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) + 1;
|
2013-09-02 16:19:08 +02:00
|
|
|
int freebuf = queuebuf_numfree() - 1;
|
|
|
|
PRINTFO("uip_len: %d, fragments: %d, free bufs: %d\n", uip_len, estimated_fragments, freebuf);
|
|
|
|
if(freebuf < estimated_fragments) {
|
|
|
|
PRINTFO("Dropping packet, not enough free bufs\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2010-11-13 17:37:42 +01:00
|
|
|
PRINTFO("Fragmentation sending packet len %d\n", uip_len);
|
2013-03-17 23:55:01 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/* Create 1st Fragment */
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("sicslowpan output: 1rst fragment ");
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/* Reset last tx status to ok in case the fragment transmissions are deferred */
|
|
|
|
last_tx_status = MAC_TX_OK;
|
|
|
|
|
|
|
|
/* move IPHC/IPv6 header */
|
2013-12-13 00:09:44 +01:00
|
|
|
memmove(packetbuf_ptr + SICSLOWPAN_FRAG1_HDR_LEN, packetbuf_ptr, packetbuf_hdr_len);
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/*
|
2008-10-14 14:26:18 +02:00
|
|
|
* FRAG1 dispatch + header
|
|
|
|
* Note that the length is in units of 8 bytes
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
/* PACKETBUF_FRAG_BUF->dispatch_size = */
|
2010-10-19 20:29:03 +02:00
|
|
|
/* uip_htons((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len); */
|
2013-12-13 00:09:44 +01:00
|
|
|
SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
|
2009-04-06 15:11:20 +02:00
|
|
|
((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len));
|
2015-09-14 15:55:26 +02:00
|
|
|
frag_tag = my_tag++;
|
|
|
|
SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG, frag_tag);
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* Copy payload and send */
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
|
2015-09-18 14:22:17 +02:00
|
|
|
packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8;
|
2015-09-14 15:55:26 +02:00
|
|
|
PRINTFO("(len %d, tag %d)\n", packetbuf_payload_len, frag_tag);
|
2013-12-13 00:09:44 +01:00
|
|
|
memcpy(packetbuf_ptr + packetbuf_hdr_len,
|
|
|
|
(uint8_t *)UIP_IP_BUF + uncomp_hdr_len, packetbuf_payload_len);
|
|
|
|
packetbuf_set_datalen(packetbuf_payload_len + packetbuf_hdr_len);
|
2010-02-06 10:42:49 +01:00
|
|
|
q = queuebuf_new_from_packetbuf();
|
|
|
|
if(q == NULL) {
|
|
|
|
PRINTFO("could not allocate queuebuf for first fragment, dropping packet\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
send_packet(&dest);
|
2010-02-06 10:42:49 +01:00
|
|
|
queuebuf_to_packetbuf(q);
|
|
|
|
queuebuf_free(q);
|
2010-02-06 21:50:24 +01:00
|
|
|
q = NULL;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2012-03-26 23:37:17 +02:00
|
|
|
/* Check tx result. */
|
|
|
|
if((last_tx_status == MAC_TX_COLLISION) ||
|
|
|
|
(last_tx_status == MAC_TX_ERR) ||
|
|
|
|
(last_tx_status == MAC_TX_ERR_FATAL)) {
|
|
|
|
PRINTFO("error in fragment tx, dropping subsequent fragments.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-03-26 23:19:02 +02:00
|
|
|
/* set processed_ip_out_len to what we already sent from the IP payload*/
|
2013-12-13 00:09:44 +01:00
|
|
|
processed_ip_out_len = packetbuf_payload_len + uncomp_hdr_len;
|
2015-10-30 11:41:59 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/*
|
2008-10-14 14:26:18 +02:00
|
|
|
* Create following fragments
|
|
|
|
* Datagram tag is already in the buffer, we need to set the
|
2008-10-14 11:42:33 +02:00
|
|
|
* FRAGN dispatch and for each fragment, the offset
|
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len = SICSLOWPAN_FRAGN_HDR_LEN;
|
|
|
|
/* PACKETBUF_FRAG_BUF->dispatch_size = */
|
2010-10-19 20:29:03 +02:00
|
|
|
/* uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */
|
2013-12-13 00:09:44 +01:00
|
|
|
SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE,
|
2009-04-06 15:11:20 +02:00
|
|
|
((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
|
2015-09-18 14:22:17 +02:00
|
|
|
packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8;
|
2012-03-26 23:19:02 +02:00
|
|
|
while(processed_ip_out_len < uip_len) {
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("sicslowpan output: fragment ");
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3;
|
2015-10-30 11:41:59 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/* Copy payload and send */
|
2013-12-13 00:09:44 +01:00
|
|
|
if(uip_len - processed_ip_out_len < packetbuf_payload_len) {
|
2008-10-14 11:42:33 +02:00
|
|
|
/* last fragment */
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_payload_len = uip_len - processed_ip_out_len;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("(offset %d, len %d, tag %d)\n",
|
2015-09-14 15:55:26 +02:00
|
|
|
processed_ip_out_len >> 3, packetbuf_payload_len, frag_tag);
|
2013-12-13 00:09:44 +01:00
|
|
|
memcpy(packetbuf_ptr + packetbuf_hdr_len,
|
|
|
|
(uint8_t *)UIP_IP_BUF + processed_ip_out_len, packetbuf_payload_len);
|
|
|
|
packetbuf_set_datalen(packetbuf_payload_len + packetbuf_hdr_len);
|
2010-02-06 21:50:24 +01:00
|
|
|
q = queuebuf_new_from_packetbuf();
|
2010-02-06 10:42:49 +01:00
|
|
|
if(q == NULL) {
|
|
|
|
PRINTFO("could not allocate queuebuf, dropping fragment\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
send_packet(&dest);
|
2010-02-06 10:42:49 +01:00
|
|
|
queuebuf_to_packetbuf(q);
|
|
|
|
queuebuf_free(q);
|
2010-02-06 21:50:24 +01:00
|
|
|
q = NULL;
|
2013-12-13 00:09:44 +01:00
|
|
|
processed_ip_out_len += packetbuf_payload_len;
|
2012-03-26 23:37:17 +02:00
|
|
|
|
|
|
|
/* Check tx result. */
|
|
|
|
if((last_tx_status == MAC_TX_COLLISION) ||
|
|
|
|
(last_tx_status == MAC_TX_ERR) ||
|
|
|
|
(last_tx_status == MAC_TX_ERR_FATAL)) {
|
|
|
|
PRINTFO("error in fragment tx, dropping subsequent fragments.\n");
|
|
|
|
return 0;
|
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
#else /* SICSLOWPAN_CONF_FRAG */
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("sicslowpan output: Packet too large to be sent without fragmentation support; dropping packet\n");
|
2008-10-14 11:42:33 +02:00
|
|
|
return 0;
|
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
2008-10-14 14:26:18 +02:00
|
|
|
} else {
|
2013-03-17 23:55:01 +01:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/*
|
|
|
|
* The packet does not need to be fragmented
|
|
|
|
* copy "payload" and send
|
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
memcpy(packetbuf_ptr + packetbuf_hdr_len, (uint8_t *)UIP_IP_BUF + uncomp_hdr_len,
|
2008-10-14 11:42:33 +02:00
|
|
|
uip_len - uncomp_hdr_len);
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_set_datalen(uip_len - uncomp_hdr_len + packetbuf_hdr_len);
|
2008-10-14 11:42:33 +02:00
|
|
|
send_packet(&dest);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
2008-10-14 14:26:18 +02:00
|
|
|
/** \brief Process a received 6lowpan packet.
|
2008-10-14 11:42:33 +02:00
|
|
|
*
|
2009-03-12 22:58:20 +01:00
|
|
|
* The 6lowpan packet is put in packetbuf by the MAC. If its a frag1 or
|
2008-10-14 11:42:33 +02:00
|
|
|
* a non-fragmented packet we first uncompress the IP header. The
|
|
|
|
* 6lowpan payload and possibly the uncompressed IP header are then
|
|
|
|
* copied in siclowpan_buf. If the IP packet is complete it is copied
|
|
|
|
* to uip_buf and the IP layer is called.
|
|
|
|
*
|
|
|
|
* \note We do not check for overlapping sicslowpan fragments
|
2008-10-14 14:26:18 +02:00
|
|
|
* (it is a SHALL in the RFC 4944 and should never happen)
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
|
|
|
static void
|
A work-in-progress rework of the Contiki MAC and radio layers. The
main ideas are:
* Separates the Contiki low-layer network stack into four layers:
network (e.g. sicslowpan / rime), Medium Access Control MAC
(e.g. CSMA), Radio Duty Cycling RDC (e.g. ContikiMAC, X-MAC), and
radio (e.g. cc2420).
* Introduces a new way to configure the network stack. Four #defines
that specify what mechanism/protocol/driver to use at the four
layers: NETSTACK_CONF_NETWORK, NETSTACK_CONF_MAC, NETSTACK_CONF_RDC,
NETSTACK_CONF_RADIO.
* Adds a callback mechanism to inform the MAC and network layers about
the fate of a transmitted packet: if the packet was not possible to
transmit, the cause of the failure is reported, and if the packets
was successfully transmitted, the number of tries before it was
finally transmitted is reported.
* NULL-protocols at both the MAC and RDC layers: nullmac and nullrdc,
which can be used when MAC and RDC functionality is not needed.
* Extends the radio API with three new functions that enable more
efficient radio duty cycling protocols: channel check, pending
packet, and receiving packet.
* New initialization mechanism, which takes advantage of the NETSTACK
#defines.
2010-02-18 22:48:39 +01:00
|
|
|
input(void)
|
2008-10-14 11:42:33 +02:00
|
|
|
{
|
|
|
|
/* size of the IP packet (read from fragment) */
|
2011-01-04 21:22:21 +01:00
|
|
|
uint16_t frag_size = 0;
|
2008-10-14 11:42:33 +02:00
|
|
|
/* offset of the fragment in the IP packet */
|
2011-01-04 21:22:21 +01:00
|
|
|
uint8_t frag_offset = 0;
|
2015-09-14 15:55:26 +02:00
|
|
|
uint8_t *buffer;
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
2015-11-11 11:44:42 +01:00
|
|
|
uint8_t is_fragment = 0;
|
2015-09-14 17:34:08 +02:00
|
|
|
int8_t frag_context = 0;
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/* tag of the fragment */
|
2011-01-04 21:22:21 +01:00
|
|
|
uint16_t frag_tag = 0;
|
2011-09-05 14:26:48 +02:00
|
|
|
uint8_t first_fragment = 0, last_fragment = 0;
|
2008-10-14 11:42:33 +02:00
|
|
|
#endif /*SICSLOWPAN_CONF_FRAG*/
|
|
|
|
|
|
|
|
/* init */
|
|
|
|
uncomp_hdr_len = 0;
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len = 0;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
/* The MAC puts the 15.4 payload inside the packetbuf data buffer */
|
|
|
|
packetbuf_ptr = packetbuf_dataptr();
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/* This is default uip_buf since we assume that this is not fragmented */
|
|
|
|
buffer = (uint8_t *)UIP_IP_BUF;
|
|
|
|
|
2013-11-22 15:10:44 +01:00
|
|
|
/* Save the RSSI of the incoming packet in case the upper layer will
|
|
|
|
want to query us for it later. */
|
|
|
|
last_rssi = (signed short)packetbuf_attr(PACKETBUF_ATTR_RSSI);
|
2015-09-14 15:55:26 +02:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
2015-09-14 15:55:26 +02:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/*
|
|
|
|
* Since we don't support the mesh and broadcast header, the first header
|
2008-10-14 14:26:18 +02:00
|
|
|
* we look for is the fragmentation header
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
switch((GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0xf800) >> 8) {
|
2008-10-14 11:42:33 +02:00
|
|
|
case SICSLOWPAN_DISPATCH_FRAG1:
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("sicslowpan input: FRAG1 ");
|
2008-10-14 11:42:33 +02:00
|
|
|
frag_offset = 0;
|
2013-12-13 00:09:44 +01:00
|
|
|
/* frag_size = (uip_ntohs(PACKETBUF_FRAG_BUF->dispatch_size) & 0x07ff); */
|
|
|
|
frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
|
|
|
|
/* frag_tag = uip_ntohs(PACKETBUF_FRAG_BUF->tag); */
|
|
|
|
frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("size %d, tag %d, offset %d)\n",
|
2008-10-14 11:42:33 +02:00
|
|
|
frag_size, frag_tag, frag_offset);
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
|
2010-04-01 12:01:01 +02:00
|
|
|
/* printf("frag1 %d %d\n", reass_tag, frag_tag);*/
|
2010-11-02 11:56:57 +01:00
|
|
|
first_fragment = 1;
|
2013-07-28 22:32:09 +02:00
|
|
|
is_fragment = 1;
|
2015-09-14 15:55:26 +02:00
|
|
|
|
|
|
|
/* Add the fragment to the fragmentation context */
|
|
|
|
frag_context = add_fragment(frag_tag, frag_size, frag_offset);
|
|
|
|
|
2015-09-18 14:22:17 +02:00
|
|
|
if(frag_context == -1) {
|
|
|
|
return;
|
|
|
|
}
|
2015-09-14 15:55:26 +02:00
|
|
|
|
|
|
|
buffer = frag_info[frag_context].first_frag;
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
case SICSLOWPAN_DISPATCH_FRAGN:
|
|
|
|
/*
|
|
|
|
* set offset, tag, size
|
2008-10-14 14:26:18 +02:00
|
|
|
* Offset is in units of 8 bytes
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("sicslowpan input: FRAGN ");
|
2013-12-13 00:09:44 +01:00
|
|
|
frag_offset = PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET];
|
|
|
|
frag_tag = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG);
|
|
|
|
frag_size = GET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE) & 0x07ff;
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("size %d, tag %d, offset %d)\n",
|
2008-10-14 11:42:33 +02:00
|
|
|
frag_size, frag_tag, frag_offset);
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len += SICSLOWPAN_FRAGN_HDR_LEN;
|
2011-09-05 14:26:48 +02:00
|
|
|
|
|
|
|
/* If this is the last fragment, we may shave off any extrenous
|
|
|
|
bytes at the end. We must be liberal in what we accept. */
|
2013-12-13 00:09:44 +01:00
|
|
|
PRINTFI("last_fragment?: processed_ip_in_len %d packetbuf_payload_len %d frag_size %d\n",
|
|
|
|
processed_ip_in_len, packetbuf_datalen() - packetbuf_hdr_len, frag_size);
|
2011-09-05 14:26:48 +02:00
|
|
|
|
2015-09-18 14:22:17 +02:00
|
|
|
/* Add the fragment to the fragmentation context (this will also
|
|
|
|
copy the payload) */
|
2015-09-14 15:55:26 +02:00
|
|
|
frag_context = add_fragment(frag_tag, frag_size, frag_offset);
|
|
|
|
|
2015-09-18 14:22:17 +02:00
|
|
|
if(frag_context == -1) {
|
|
|
|
return;
|
|
|
|
}
|
2015-09-14 15:55:26 +02:00
|
|
|
|
2015-09-18 14:22:17 +02:00
|
|
|
/* Ok - add_fragment will store the fragment automatically - so
|
|
|
|
we should not store more */
|
2015-09-14 15:55:26 +02:00
|
|
|
buffer = NULL;
|
|
|
|
|
|
|
|
if(frag_info[frag_context].reassembled_len >= frag_size) {
|
2011-09-05 14:26:48 +02:00
|
|
|
last_fragment = 1;
|
|
|
|
}
|
2013-07-28 22:32:09 +02:00
|
|
|
is_fragment = 1;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
if(is_fragment && !first_fragment) {
|
2008-10-14 11:42:33 +02:00
|
|
|
/* this is a FRAGN, skip the header compression dispatch section */
|
|
|
|
goto copypayload;
|
|
|
|
}
|
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
|
|
|
|
|
|
|
/* Process next dispatch and headers */
|
2010-02-25 16:50:58 +01:00
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
|
2013-12-13 00:09:44 +01:00
|
|
|
if((PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH] & 0xe0) == SICSLOWPAN_DISPATCH_IPHC) {
|
2010-02-25 16:50:58 +01:00
|
|
|
PRINTFI("sicslowpan input: IPHC\n");
|
2015-09-14 15:55:26 +02:00
|
|
|
uncompress_hdr_iphc(buffer, frag_size);
|
2010-02-25 16:50:58 +01:00
|
|
|
} else
|
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
|
2013-12-13 00:09:44 +01:00
|
|
|
switch(PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH]) {
|
2008-10-14 11:42:33 +02:00
|
|
|
case SICSLOWPAN_DISPATCH_IPV6:
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("sicslowpan input: IPV6\n");
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* Put uncompressed IP header in sicslowpan_buf. */
|
2015-09-14 15:55:26 +02:00
|
|
|
memcpy(buffer, packetbuf_ptr + packetbuf_hdr_len, UIP_IPH_LEN);
|
2008-10-14 11:42:33 +02:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
/* Update uncomp_hdr_len and packetbuf_hdr_len. */
|
|
|
|
packetbuf_hdr_len += UIP_IPH_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
uncomp_hdr_len += UIP_IPH_LEN;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* unknown header */
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("sicslowpan input: unknown dispatch: %u\n",
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH]);
|
2008-10-14 11:42:33 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-10-30 11:41:59 +01:00
|
|
|
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
copypayload:
|
|
|
|
#endif /*SICSLOWPAN_CONF_FRAG*/
|
|
|
|
/*
|
2013-12-13 00:09:44 +01:00
|
|
|
* copy "payload" from the packetbuf buffer to the sicslowpan_buf
|
2008-10-14 11:42:33 +02:00
|
|
|
* if this is a first fragment or not fragmented packet,
|
|
|
|
* we have already copied the compressed headers, uncomp_hdr_len
|
2013-12-13 00:09:44 +01:00
|
|
|
* and packetbuf_hdr_len are non 0, frag_offset is.
|
2008-10-14 11:42:33 +02:00
|
|
|
* If this is a subsequent fragment, this is the contrary.
|
2008-10-14 14:26:18 +02:00
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
if(packetbuf_datalen() < packetbuf_hdr_len) {
|
2010-06-06 14:44:12 +02:00
|
|
|
PRINTF("SICSLOWPAN: packet dropped due to header > total packet\n");
|
|
|
|
return;
|
|
|
|
}
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_payload_len = packetbuf_datalen() - packetbuf_hdr_len;
|
2013-03-17 23:55:01 +01:00
|
|
|
|
|
|
|
/* Sanity-check size of incoming packet to avoid buffer overflow */
|
|
|
|
{
|
|
|
|
int req_size = UIP_LLH_LEN + uncomp_hdr_len + (uint16_t)(frag_offset << 3)
|
2013-12-13 00:09:44 +01:00
|
|
|
+ packetbuf_payload_len;
|
2015-09-14 15:55:26 +02:00
|
|
|
if(req_size > sizeof(uip_buf)) {
|
2013-03-17 23:55:01 +01:00
|
|
|
PRINTF(
|
2015-09-14 15:55:26 +02:00
|
|
|
"SICSLOWPAN: packet dropped, minimum required IP_BUF size: %d+%d+%d+%d=%d (current size: %u)\n",
|
2013-03-17 23:55:01 +01:00
|
|
|
UIP_LLH_LEN, uncomp_hdr_len, (uint16_t)(frag_offset << 3),
|
2015-09-14 15:55:26 +02:00
|
|
|
packetbuf_payload_len, req_size, sizeof(uip_buf));
|
2013-03-17 23:55:01 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-14 15:55:26 +02:00
|
|
|
/* copy the payload if buffer is non-null - which is only the case with first fragment
|
|
|
|
or packets that are non fragmented */
|
|
|
|
if(buffer != NULL) {
|
|
|
|
memcpy((uint8_t *)buffer + uncomp_hdr_len, packetbuf_ptr + packetbuf_hdr_len, packetbuf_payload_len);
|
|
|
|
}
|
2015-10-30 11:41:59 +01:00
|
|
|
|
2012-03-26 23:19:02 +02:00
|
|
|
/* update processed_ip_in_len if fragment, sicslowpan_len otherwise */
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
2010-11-02 11:56:57 +01:00
|
|
|
if(frag_size > 0) {
|
|
|
|
/* Add the size of the header only for the first fragment. */
|
|
|
|
if(first_fragment != 0) {
|
2015-09-14 15:55:26 +02:00
|
|
|
frag_info[frag_context].reassembled_len = uncomp_hdr_len + packetbuf_payload_len;
|
2015-09-18 14:22:17 +02:00
|
|
|
frag_info[frag_context].first_frag_len = uncomp_hdr_len + packetbuf_payload_len;
|
2008-10-14 14:26:18 +02:00
|
|
|
}
|
2011-09-05 14:26:48 +02:00
|
|
|
/* For the last fragment, we are OK if there is extrenous bytes at
|
|
|
|
the end of the packet. */
|
|
|
|
if(last_fragment != 0) {
|
2015-09-14 15:55:26 +02:00
|
|
|
frag_info[frag_context].reassembled_len = frag_size;
|
|
|
|
/* copy to uip */
|
|
|
|
copy_frags2uip(frag_context);
|
2011-09-05 14:26:48 +02:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have a full IP packet in sicslowpan_buf, deliver it to
|
|
|
|
* the IP stack
|
|
|
|
*/
|
2015-09-14 15:55:26 +02:00
|
|
|
if(!is_fragment || last_fragment) {
|
|
|
|
/* packet is in uip already - just set length */
|
|
|
|
if(is_fragment != 0 && last_fragment != 0) {
|
|
|
|
uip_len = frag_size;
|
|
|
|
} else {
|
|
|
|
uip_len = packetbuf_payload_len + uncomp_hdr_len;
|
|
|
|
}
|
2015-09-18 14:22:17 +02:00
|
|
|
#else
|
|
|
|
uip_len = packetbuf_payload_len + uncomp_hdr_len;
|
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("sicslowpan input: IP packet ready (length %d)\n",
|
2015-09-14 15:55:26 +02:00
|
|
|
uip_len);
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#if DEBUG
|
|
|
|
{
|
2011-10-27 17:13:26 +02:00
|
|
|
uint16_t ndx;
|
2015-09-14 15:55:26 +02:00
|
|
|
PRINTF("after decompression %u:", UIP_IP_BUF->len[1]);
|
|
|
|
for (ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
|
|
|
|
uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
|
2011-10-27 17:13:26 +02:00
|
|
|
PRINTF("%02x", data);
|
2010-02-25 16:50:58 +01:00
|
|
|
}
|
|
|
|
PRINTF("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-10-13 15:09:40 +02:00
|
|
|
/* if callback is set then set attributes and call */
|
2011-10-20 12:37:56 +02:00
|
|
|
if(callback) {
|
2011-10-13 15:09:40 +02:00
|
|
|
set_packet_attrs();
|
|
|
|
callback->input_callback();
|
|
|
|
}
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
tcpip_input();
|
2008-10-14 14:26:18 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2008-10-14 14:26:18 +02:00
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/* \brief 6lowpan init function (called by the MAC layer) */
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
void
|
A work-in-progress rework of the Contiki MAC and radio layers. The
main ideas are:
* Separates the Contiki low-layer network stack into four layers:
network (e.g. sicslowpan / rime), Medium Access Control MAC
(e.g. CSMA), Radio Duty Cycling RDC (e.g. ContikiMAC, X-MAC), and
radio (e.g. cc2420).
* Introduces a new way to configure the network stack. Four #defines
that specify what mechanism/protocol/driver to use at the four
layers: NETSTACK_CONF_NETWORK, NETSTACK_CONF_MAC, NETSTACK_CONF_RDC,
NETSTACK_CONF_RADIO.
* Adds a callback mechanism to inform the MAC and network layers about
the fate of a transmitted packet: if the packet was not possible to
transmit, the cause of the failure is reported, and if the packets
was successfully transmitted, the number of tries before it was
finally transmitted is reported.
* NULL-protocols at both the MAC and RDC layers: nullmac and nullrdc,
which can be used when MAC and RDC functionality is not needed.
* Extends the radio API with three new functions that enable more
efficient radio duty cycling protocols: channel check, pending
packet, and receiving packet.
* New initialization mechanism, which takes advantage of the NETSTACK
#defines.
2010-02-18 22:48:39 +01:00
|
|
|
sicslowpan_init(void)
|
2008-10-14 11:42:33 +02:00
|
|
|
{
|
2008-10-14 14:26:18 +02:00
|
|
|
/*
|
2008-10-14 11:42:33 +02:00
|
|
|
* Set out output function as the function to be called from uIP to
|
2008-10-14 14:26:18 +02:00
|
|
|
* send a packet.
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2015-09-18 14:22:17 +02:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
tcpip_set_outputfunc(output);
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
|
2010-12-14 00:27:40 +01:00
|
|
|
/* Preinitialize any address contexts for better header compression
|
|
|
|
* (Saves up to 13 bytes per 6lowpan packet)
|
|
|
|
* The platform contiki-conf.h file can override this using e.g.
|
|
|
|
* #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xbb;addr_contexts[0].prefix[1]=0xbb;}
|
|
|
|
*/
|
2015-10-30 11:41:59 +01:00
|
|
|
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
2010-12-14 00:27:40 +01:00
|
|
|
addr_contexts[0].used = 1;
|
2010-02-25 16:50:58 +01:00
|
|
|
addr_contexts[0].number = 0;
|
2010-12-14 00:27:40 +01:00
|
|
|
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0
|
2015-10-30 11:41:59 +01:00
|
|
|
SICSLOWPAN_CONF_ADDR_CONTEXT_0;
|
2010-12-14 00:27:40 +01:00
|
|
|
#else
|
2015-10-30 11:41:59 +01:00
|
|
|
addr_contexts[0].prefix[0] = 0xaa;
|
2010-02-25 16:50:58 +01:00
|
|
|
addr_contexts[0].prefix[1] = 0xaa;
|
2010-12-14 00:27:40 +01:00
|
|
|
#endif
|
2010-03-19 09:15:20 +01:00
|
|
|
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
|
2010-12-14 00:27:40 +01:00
|
|
|
|
2009-04-06 15:11:20 +02:00
|
|
|
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1
|
2010-03-19 09:15:20 +01:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for(i = 1; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
|
2010-12-14 00:27:40 +01:00
|
|
|
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1
|
2015-10-30 11:41:59 +01:00
|
|
|
if (i==1) {
|
|
|
|
addr_contexts[1].used = 1;
|
|
|
|
addr_contexts[1].number = 1;
|
|
|
|
SICSLOWPAN_CONF_ADDR_CONTEXT_1;
|
2010-12-14 00:27:40 +01:00
|
|
|
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
|
|
|
|
} else if (i==2) {
|
2015-10-30 11:41:59 +01:00
|
|
|
addr_contexts[2].used = 1;
|
|
|
|
addr_contexts[2].number = 2;
|
|
|
|
SICSLOWPAN_CONF_ADDR_CONTEXT_2;
|
2010-12-14 00:27:40 +01:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
addr_contexts[i].used = 0;
|
2015-10-30 11:41:59 +01:00
|
|
|
}
|
2010-12-14 00:27:40 +01:00
|
|
|
#else
|
2010-03-19 09:15:20 +01:00
|
|
|
addr_contexts[i].used = 0;
|
2010-12-14 00:27:40 +01:00
|
|
|
#endif /* SICSLOWPAN_CONF_ADDR_CONTEXT_1 */
|
2010-03-19 09:15:20 +01:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2009-04-06 15:11:20 +02:00
|
|
|
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
2013-11-22 15:10:44 +01:00
|
|
|
int
|
|
|
|
sicslowpan_get_last_rssi(void)
|
|
|
|
{
|
|
|
|
return last_rssi;
|
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
2010-02-23 21:09:11 +01:00
|
|
|
const struct network_driver sicslowpan_driver = {
|
|
|
|
"sicslowpan",
|
A work-in-progress rework of the Contiki MAC and radio layers. The
main ideas are:
* Separates the Contiki low-layer network stack into four layers:
network (e.g. sicslowpan / rime), Medium Access Control MAC
(e.g. CSMA), Radio Duty Cycling RDC (e.g. ContikiMAC, X-MAC), and
radio (e.g. cc2420).
* Introduces a new way to configure the network stack. Four #defines
that specify what mechanism/protocol/driver to use at the four
layers: NETSTACK_CONF_NETWORK, NETSTACK_CONF_MAC, NETSTACK_CONF_RDC,
NETSTACK_CONF_RADIO.
* Adds a callback mechanism to inform the MAC and network layers about
the fate of a transmitted packet: if the packet was not possible to
transmit, the cause of the failure is reported, and if the packets
was successfully transmitted, the number of tries before it was
finally transmitted is reported.
* NULL-protocols at both the MAC and RDC layers: nullmac and nullrdc,
which can be used when MAC and RDC functionality is not needed.
* Extends the radio API with three new functions that enable more
efficient radio duty cycling protocols: channel check, pending
packet, and receiving packet.
* New initialization mechanism, which takes advantage of the NETSTACK
#defines.
2010-02-18 22:48:39 +01:00
|
|
|
sicslowpan_init,
|
2010-02-23 21:09:11 +01:00
|
|
|
input
|
A work-in-progress rework of the Contiki MAC and radio layers. The
main ideas are:
* Separates the Contiki low-layer network stack into four layers:
network (e.g. sicslowpan / rime), Medium Access Control MAC
(e.g. CSMA), Radio Duty Cycling RDC (e.g. ContikiMAC, X-MAC), and
radio (e.g. cc2420).
* Introduces a new way to configure the network stack. Four #defines
that specify what mechanism/protocol/driver to use at the four
layers: NETSTACK_CONF_NETWORK, NETSTACK_CONF_MAC, NETSTACK_CONF_RDC,
NETSTACK_CONF_RADIO.
* Adds a callback mechanism to inform the MAC and network layers about
the fate of a transmitted packet: if the packet was not possible to
transmit, the cause of the failure is reported, and if the packets
was successfully transmitted, the number of tries before it was
finally transmitted is reported.
* NULL-protocols at both the MAC and RDC layers: nullmac and nullrdc,
which can be used when MAC and RDC functionality is not needed.
* Extends the radio API with three new functions that enable more
efficient radio duty cycling protocols: channel check, pending
packet, and receiving packet.
* New initialization mechanism, which takes advantage of the NETSTACK
#defines.
2010-02-18 22:48:39 +01:00
|
|
|
};
|
|
|
|
/*--------------------------------------------------------------------*/
|
2008-10-14 11:42:33 +02:00
|
|
|
/** @} */
|
2015-09-14 15:55:26 +02:00
|
|
|
|