2008-10-14 11:42:33 +02:00
|
|
|
/**
|
|
|
|
* \addtogroup sicslowpan
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* \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
|
|
|
*/
|
|
|
|
|
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
|
|
|
|
*
|
2010-03-09 17:19:44 +01:00
|
|
|
* -Verify TC/FL compression works
|
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
|
|
|
#if UIP_CONF_IPV6
|
|
|
|
|
|
|
|
#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__)
|
2013-12-13 00:09:44 +01:00
|
|
|
#define PRINTPACKETBUF() PRINTF("packetbuf buffer: "); for(p = 0; p < packetbuf_datalen(); p++){PRINTF("%.2X", *(packetbuf_ptr + p));} PRINTF("\n")
|
2008-10-14 11:42:33 +02:00
|
|
|
#define PRINTUIPBUF() PRINTF("UIP buffer: "); for(p = 0; p < uip_len; p++){PRINTF("%.2X", uip_buf[p]);}PRINTF("\n")
|
|
|
|
#define PRINTSICSLOWPANBUF() PRINTF("SICSLOWPAN buffer: "); for(p = 0; p < sicslowpan_len; p++){PRINTF("%.2X", sicslowpan_buf[p]);}PRINTF("\n")
|
|
|
|
#else
|
2009-07-10 15:33:45 +02:00
|
|
|
#define PRINTFI(...)
|
|
|
|
#define PRINTFO(...)
|
2009-03-12 22:58:20 +01:00
|
|
|
#define PRINTPACKETBUF()
|
2008-10-14 14:26:18 +02:00
|
|
|
#define PRINTUIPBUF()
|
2008-10-14 11:42:33 +02:00
|
|
|
#define PRINTSICSLOWPANBUF()
|
|
|
|
#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
|
|
|
|
* @{
|
|
|
|
*/
|
2010-05-24 16:28:56 +02:00
|
|
|
#define SICSLOWPAN_IP_BUF ((struct uip_ip_hdr *)&sicslowpan_buf[UIP_LLH_LEN])
|
|
|
|
#define SICSLOWPAN_UDP_BUF ((struct uip_udp_hdr *)&sicslowpan_buf[UIP_LLIPH_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
|
|
|
|
|
|
|
/** \brief Some MAC layers need a minimum payload, which is
|
|
|
|
configurable through the SICSLOWPAN_CONF_MIN_MAC_PAYLOAD
|
|
|
|
option. */
|
|
|
|
#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
|
|
|
#ifdef SICSLOWPAN_NH_COMPRESSOR
|
|
|
|
/** A pointer to the additional compressor */
|
|
|
|
extern struct sicslowpan_nh_compressor SICSLOWPAN_NH_COMPRESSOR;
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
/** @} */
|
|
|
|
|
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
/** \name Fragmentation related variables
|
|
|
|
* @{
|
|
|
|
*/
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2011-01-04 21:22:21 +01:00
|
|
|
static uint16_t sicslowpan_len;
|
2010-05-24 16:28:56 +02:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/**
|
|
|
|
* The buffer used for the 6lowpan reassembly.
|
|
|
|
* This buffer contains only the IPv6 packet (no MAC header, 6lowpan, etc).
|
|
|
|
* It has a fix size as we do not use dynamic memory allocation.
|
|
|
|
*/
|
2010-05-24 16:28:56 +02:00
|
|
|
static uip_buf_t sicslowpan_aligned_buf;
|
|
|
|
#define sicslowpan_buf (sicslowpan_aligned_buf.u8)
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/** The total length of the IPv6 packet in the sicslowpan_buf. */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* length of the ip packet already sent / received.
|
|
|
|
* It includes IP and transport headers.
|
|
|
|
*/
|
2012-03-26 23:19:02 +02:00
|
|
|
static uint16_t processed_ip_in_len;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/** Datagram tag to be put in the fragments I send. */
|
2011-01-04 21:22:21 +01:00
|
|
|
static uint16_t my_tag;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/** When reassembling, the tag in the fragments being merged. */
|
2011-01-04 21:22:21 +01:00
|
|
|
static uint16_t reass_tag;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/** When reassembling, the source address of the fragments being merged */
|
2013-12-12 23:58:52 +01:00
|
|
|
linkaddr_t frag_sender;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/** Reassembly %process %timer. */
|
|
|
|
static struct timer reass_timer;
|
|
|
|
|
|
|
|
/** @} */
|
|
|
|
#else /* SICSLOWPAN_CONF_FRAG */
|
|
|
|
/** The buffer used for the 6lowpan processing is uip_buf.
|
|
|
|
We do not use any additional buffer.*/
|
|
|
|
#define sicslowpan_buf uip_buf
|
|
|
|
#define sicslowpan_len uip_len
|
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
|
|
|
|
2013-11-22 15:10:44 +01:00
|
|
|
static int last_rssi;
|
|
|
|
|
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
|
2010-03-19 09:15:20 +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
|
|
|
|
2010-06-06 14:44:12 +02:00
|
|
|
/* Uncompression of linklocal */
|
|
|
|
/* 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
|
|
|
/*--------------------------------------------------------------------*/
|
2010-02-25 16:50:58 +01:00
|
|
|
/** \name HC06 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
|
|
|
{
|
2010-03-19 09:15:20 +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
|
|
|
*
|
|
|
|
*
|
2010-02-25 16:50:58 +01:00
|
|
|
* HC-06 (draft-ietf-6lowpan-hc, version 6)\n
|
|
|
|
* http://tools.ietf.org/html/draft-ietf-6lowpan-hc-06
|
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
|
2013-12-13 00:09:44 +01:00
|
|
|
compress_hdr_hc06(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
|
|
|
*/
|
2010-02-25 16:50:58 +01:00
|
|
|
|
|
|
|
/* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */
|
|
|
|
tmp = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
|
|
|
|
tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
|
|
|
|
|
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*/
|
2010-03-17 13:08:59 +01:00
|
|
|
#ifdef SICSLOWPAN_NH_COMPRESSOR
|
|
|
|
if(SICSLOWPAN_NH_COMPRESSOR.is_compressable(UIP_IP_BUF->proto)) {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 |= SICSLOWPAN_IPHC_NH_C;
|
2010-03-17 13:08:59 +01:00
|
|
|
}
|
|
|
|
#endif
|
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",
|
|
|
|
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 */
|
2011-04-06 20:14:30 +02:00
|
|
|
} else if(uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) &&
|
|
|
|
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,
|
2013-12-13 00:09:44 +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 */
|
2011-04-06 20:14:30 +02:00
|
|
|
} else if(uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) &&
|
|
|
|
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",
|
2010-10-19 20:29:03 +02: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) =
|
2012-02-17 23:45:13 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
2010-03-26 11:28:51 +01:00
|
|
|
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
|
2012-02-17 23:45:13 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
|
2010-03-26 11:28:51 +01:00
|
|
|
SICSLOWPAN_UDP_4_BIT_PORT_MIN));
|
|
|
|
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) =
|
2012-02-17 23:45:13 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
|
2010-03-26 11:28:51 +01:00
|
|
|
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
|
|
|
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) =
|
2012-02-17 23:45:13 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
2010-03-26 11:28:51 +01:00
|
|
|
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
|
|
|
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
|
|
|
|
2010-03-17 13:08:59 +01:00
|
|
|
#ifdef SICSLOWPAN_NH_COMPRESSOR
|
|
|
|
/* if nothing to compress just return zero */
|
|
|
|
hc06_ptr += SICSLOWPAN_NH_COMPRESSOR.compress(hc06_ptr, &uncomp_hdr_len);
|
|
|
|
#endif
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/**
|
2010-02-25 16:50:58 +01:00
|
|
|
* \brief Uncompress HC06 (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
|
2010-02-25 16:50:58 +01:00
|
|
|
* HC06.
|
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
|
|
|
|
*
|
|
|
|
* \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
|
2011-01-04 21:22:21 +01:00
|
|
|
uncompress_hdr_hc06(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 */
|
|
|
|
memcpy(&SICSLOWPAN_IP_BUF->tcflow, hc06_ptr + 1, 3);
|
|
|
|
tmp = *hc06_ptr;
|
|
|
|
hc06_ptr += 4;
|
|
|
|
/* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */
|
|
|
|
/* set version, pick highest DSCP bits and set in vtc */
|
|
|
|
SICSLOWPAN_IP_BUF->vtc = 0x60 | ((tmp >> 2) & 0x0f);
|
|
|
|
/* ECN rolled down two steps + lowest DSCP bits at top two bits */
|
|
|
|
SICSLOWPAN_IP_BUF->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
|
|
|
|
(SICSLOWPAN_IP_BUF->tcflow & 0x0f);
|
|
|
|
} else {
|
|
|
|
/* Traffic class is compressed (set version and no TC)*/
|
|
|
|
SICSLOWPAN_IP_BUF->vtc = 0x60;
|
|
|
|
/* highest flow label bits + ECN bits */
|
|
|
|
SICSLOWPAN_IP_BUF->tcflow = (*hc06_ptr & 0x0F) |
|
|
|
|
((*hc06_ptr >> 2) & 0x30);
|
|
|
|
memcpy(&SICSLOWPAN_IP_BUF->flow, hc06_ptr + 1, 2);
|
|
|
|
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 */
|
|
|
|
SICSLOWPAN_IP_BUF->vtc = 0x60 | ((*hc06_ptr >> 2) & 0x0f);
|
|
|
|
SICSLOWPAN_IP_BUF->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30);
|
|
|
|
SICSLOWPAN_IP_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 */
|
|
|
|
SICSLOWPAN_IP_BUF->vtc = 0x60;
|
|
|
|
SICSLOWPAN_IP_BUF->tcflow = 0;
|
|
|
|
SICSLOWPAN_IP_BUF->flow = 0;
|
|
|
|
}
|
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 */
|
2010-02-25 16:50:58 +01:00
|
|
|
SICSLOWPAN_IP_BUF->proto = *hc06_ptr;
|
|
|
|
PRINTF("IPHC: next header inline: %d\n", SICSLOWPAN_IP_BUF->proto);
|
|
|
|
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) {
|
|
|
|
SICSLOWPAN_IP_BUF->ttl = ttl_values[iphc0 & 0x03];
|
|
|
|
} else {
|
|
|
|
SICSLOWPAN_IP_BUF->ttl = *hc06_ptr;
|
|
|
|
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 */
|
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF->srcipaddr,
|
|
|
|
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 */
|
2010-05-31 22:42:27 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF->srcipaddr, llprefix, unc_llconf[tmp],
|
|
|
|
(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
|
|
|
|
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF->destipaddr, prefix,
|
|
|
|
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) {
|
|
|
|
uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
|
2013-12-13 00:09:44 +01:00
|
|
|
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) {
|
2010-02-25 16:50:58 +01:00
|
|
|
PRINTF("sicslowpan uncompress_hdr: error context not found\n");
|
|
|
|
return;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2010-05-31 22:42:27 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF->destipaddr, context->prefix,
|
|
|
|
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 */
|
2010-05-31 22:42:27 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF->destipaddr, llprefix,
|
|
|
|
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;
|
2008-10-14 11:42:33 +02:00
|
|
|
SICSLOWPAN_IP_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:
|
2010-02-25 16:50:58 +01:00
|
|
|
/* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 3, 2);
|
2010-03-26 11:28:51 +01:00
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n",
|
2010-10-19 20:29:03 +02:00
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
2010-03-26 11:28:51 +01:00
|
|
|
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 */
|
2010-03-26 11:28:51 +01:00
|
|
|
PRINTF("IPHC: Decompressing destination\n");
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
|
2010-10-19 20:29:03 +02:00
|
|
|
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
|
2010-03-26 11:28:51 +01:00
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
2010-10-19 20:29:03 +02:00
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
2010-03-26 11:28:51 +01:00
|
|
|
hc06_ptr += 4;
|
2010-02-25 16:50:58 +01:00
|
|
|
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*/
|
2010-03-26 11:28:51 +01:00
|
|
|
PRINTF("IPHC: Decompressing source\n");
|
2010-10-19 20:29:03 +02:00
|
|
|
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
|
2010-03-26 11:28:51 +01:00
|
|
|
(*(hc06_ptr + 1)));
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 2, 2);
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
2010-10-19 20:29:03 +02:00
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
2010-03-26 11:28:51 +01:00
|
|
|
hc06_ptr += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SICSLOWPAN_NHC_UDP_CS_P_11:
|
|
|
|
/* 1 byte for NHC, 1 byte for ports */
|
2010-10-19 20:29:03 +02:00
|
|
|
SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
2010-03-26 11:28:51 +01:00
|
|
|
(*(hc06_ptr + 1) >> 4));
|
2010-10-19 20:29:03 +02:00
|
|
|
SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
2010-03-26 11:28:51 +01:00
|
|
|
((*(hc06_ptr + 1)) & 0x0F));
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
|
2010-10-19 20:29:03 +02:00
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
|
2010-03-26 11:28:51 +01:00
|
|
|
hc06_ptr += 2;
|
|
|
|
break;
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
default:
|
|
|
|
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 */
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr, 2);
|
|
|
|
hc06_ptr += 2;
|
|
|
|
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum included\n");
|
|
|
|
} else {
|
|
|
|
PRINTF("IPHC: sicslowpan uncompress_hdr: checksum *NOT* included\n");
|
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
uncomp_hdr_len += UIP_UDPH_LEN;
|
|
|
|
}
|
2010-03-17 13:08:59 +01:00
|
|
|
#ifdef SICSLOWPAN_NH_COMPRESSOR
|
|
|
|
else {
|
|
|
|
hc06_ptr += SICSLOWPAN_NH_COMPRESSOR.uncompress(hc06_ptr, sicslowpan_buf, &uncomp_hdr_len);
|
|
|
|
}
|
|
|
|
#endif
|
2008-10-14 11:42:33 +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
|
|
|
|
|
|
|
/* 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 */
|
2013-11-16 14:44:14 +01:00
|
|
|
SICSLOWPAN_IP_BUF->len[0] = len >> 8;
|
|
|
|
SICSLOWPAN_IP_BUF->len[1] = len & 0x00FF;
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
|
|
|
/* This is a 1st fragment */
|
|
|
|
SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
|
|
|
|
SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* length field in UDP header */
|
|
|
|
if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) {
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->udplen, &SICSLOWPAN_IP_BUF->len[0], 2);
|
|
|
|
}
|
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
|
|
|
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1
|
2008-10-14 11:42:33 +02:00
|
|
|
/*--------------------------------------------------------------------*/
|
2008-10-14 14:26:18 +02:00
|
|
|
/** \name HC1 compression and uncompression functions
|
2008-10-14 11:42:33 +02:00
|
|
|
* @{ */
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/**
|
|
|
|
* \brief Compress IP/UDP header using HC1 and HC_UDP
|
|
|
|
*
|
|
|
|
* 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
|
|
|
*
|
|
|
|
*
|
2008-10-14 11:42:33 +02:00
|
|
|
* If we can compress everything, we use HC1 dispatch, if not we use
|
|
|
|
* IPv6 dispatch.\n
|
|
|
|
* We can compress everything if:
|
|
|
|
* - IP version is
|
|
|
|
* - Flow label and traffic class are 0
|
|
|
|
* - Both src and dest ip addresses are link local
|
|
|
|
* - Both src and dest interface ID are recoverable from lower layer
|
|
|
|
* header
|
|
|
|
* - Next header is either ICMP, UDP or TCP
|
|
|
|
* Moreover, if next header is UDP, we try to compress it using HC_UDP.
|
|
|
|
* This is feasible is both ports are between F0B0 and F0B0 + 15\n\n
|
|
|
|
*
|
|
|
|
* Resulting header structure:
|
|
|
|
* - For ICMP, TCP, non compressed UDP\n
|
|
|
|
* HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)\n
|
|
|
|
* \verbatim
|
|
|
|
* 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
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | LoWPAN HC1 Dsp | HC1 encoding | IPv6 Hop limit| L4 hdr + data|
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
2008-10-14 14:26:18 +02:00
|
|
|
* | ...
|
2008-10-14 11:42:33 +02:00
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* \endverbatim
|
2008-10-14 14:26:18 +02:00
|
|
|
*
|
2008-10-14 11:42:33 +02:00
|
|
|
* - For compressed UDP
|
|
|
|
* HC1 encoding = 11111011, HC_UDP encoding = 11100000\n
|
|
|
|
* \verbatim
|
|
|
|
* 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
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* | LoWPAN HC1 Dsp| HC1 encoding | HC_UDP encod.| IPv6 Hop limit|
|
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
2008-10-14 14:26:18 +02:00
|
|
|
* | src p.| dst p.| UDP checksum | L4 data...
|
2008-10-14 11:42:33 +02:00
|
|
|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
|
|
* \endverbatim
|
|
|
|
*
|
2013-12-13 00:09:44 +01:00
|
|
|
* \param link_destaddr L2 destination address, needed to compress the
|
2008-10-14 14:26:18 +02:00
|
|
|
* IP destination field
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
|
|
|
static void
|
2013-12-13 00:09:44 +01:00
|
|
|
compress_hdr_hc1(linkaddr_t *link_destaddr)
|
2008-10-14 11:42:33 +02:00
|
|
|
{
|
|
|
|
/*
|
2008-10-14 14:26:18 +02:00
|
|
|
* Check if all the assumptions for full compression
|
2008-10-14 11:42:33 +02:00
|
|
|
* are valid :
|
|
|
|
*/
|
|
|
|
if(UIP_IP_BUF->vtc != 0x60 ||
|
2008-10-14 14:26:18 +02:00
|
|
|
UIP_IP_BUF->tcflow != 0 ||
|
|
|
|
UIP_IP_BUF->flow != 0 ||
|
2008-10-14 11:42:33 +02:00
|
|
|
!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) ||
|
|
|
|
!uip_is_addr_mac_addr_based(&UIP_IP_BUF->srcipaddr, &uip_lladdr) ||
|
2008-10-14 14:26:18 +02:00
|
|
|
!uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) ||
|
2008-10-14 11:42:33 +02:00
|
|
|
!uip_is_addr_mac_addr_based(&UIP_IP_BUF->destipaddr,
|
2013-12-13 00:09:44 +01:00
|
|
|
(uip_lladdr_t *)link_destaddr) ||
|
2008-10-14 11:42:33 +02:00
|
|
|
(UIP_IP_BUF->proto != UIP_PROTO_ICMP6 &&
|
|
|
|
UIP_IP_BUF->proto != UIP_PROTO_UDP &&
|
|
|
|
UIP_IP_BUF->proto != UIP_PROTO_TCP))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* IPV6 DISPATCH
|
2008-10-14 14:26:18 +02:00
|
|
|
* Something cannot be compressed, use IPV6 DISPATCH,
|
2013-12-13 00:09:44 +01:00
|
|
|
* compress nothing, copy IPv6 header in packetbuf buffer
|
2008-10-14 14:26:18 +02: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;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* HC1 DISPATCH
|
|
|
|
* maximum compresssion:
|
|
|
|
* All fields in the IP header but Hop Limit are elided
|
|
|
|
* If next header is UDP, we compress UDP header using HC2
|
|
|
|
*/
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH] = SICSLOWPAN_DISPATCH_HC1;
|
2008-10-14 11:42:33 +02:00
|
|
|
uncomp_hdr_len += UIP_IPH_LEN;
|
|
|
|
switch(UIP_IP_BUF->proto) {
|
|
|
|
case UIP_PROTO_ICMP6:
|
|
|
|
/* HC1 encoding and ttl */
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_HC1_PTR[PACKETBUF_HC1_ENCODING] = 0xFC;
|
|
|
|
PACKETBUF_HC1_PTR[PACKETBUF_HC1_TTL] = UIP_IP_BUF->ttl;
|
|
|
|
packetbuf_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
#if UIP_CONF_TCP
|
|
|
|
case UIP_PROTO_TCP:
|
|
|
|
/* HC1 encoding and ttl */
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_HC1_PTR[PACKETBUF_HC1_ENCODING] = 0xFE;
|
|
|
|
PACKETBUF_HC1_PTR[PACKETBUF_HC1_TTL] = UIP_IP_BUF->ttl;
|
|
|
|
packetbuf_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
#endif /* UIP_CONF_TCP */
|
|
|
|
#if UIP_CONF_UDP
|
|
|
|
case UIP_PROTO_UDP:
|
2008-10-14 14:26:18 +02:00
|
|
|
/*
|
2008-10-14 11:42:33 +02:00
|
|
|
* try to compress UDP header (we do only full compression).
|
|
|
|
* This is feasible if both src and dest ports are between
|
|
|
|
* SICSLOWPAN_UDP_PORT_MIN and SICSLOWPAN_UDP_PORT_MIN + 15
|
|
|
|
*/
|
|
|
|
PRINTF("local/remote port %u/%u\n",UIP_UDP_BUF->srcport,UIP_UDP_BUF->destport);
|
2010-10-19 20:29:03 +02:00
|
|
|
if(UIP_HTONS(UIP_UDP_BUF->srcport) >= SICSLOWPAN_UDP_PORT_MIN &&
|
|
|
|
UIP_HTONS(UIP_UDP_BUF->srcport) < SICSLOWPAN_UDP_PORT_MAX &&
|
|
|
|
UIP_HTONS(UIP_UDP_BUF->destport) >= SICSLOWPAN_UDP_PORT_MIN &&
|
|
|
|
UIP_HTONS(UIP_UDP_BUF->destport) < SICSLOWPAN_UDP_PORT_MAX) {
|
2008-10-14 11:42:33 +02:00
|
|
|
/* HC1 encoding */
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_HC1_ENCODING] = 0xFB;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* HC_UDP encoding, ttl, src and dest ports, checksum */
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_UDP_ENCODING] = 0xE0;
|
|
|
|
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_TTL] = UIP_IP_BUF->ttl;
|
2010-05-24 16:28:56 +02:00
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_PORTS] =
|
2012-02-17 23:45:13 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
|
2009-04-06 15:11:20 +02:00
|
|
|
SICSLOWPAN_UDP_PORT_MIN) << 4) +
|
2012-02-17 23:45:13 +01:00
|
|
|
(uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) - SICSLOWPAN_UDP_PORT_MIN));
|
2013-12-13 00:09:44 +01:00
|
|
|
memcpy(&PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_CHKSUM], &UIP_UDP_BUF->udpchksum, 2);
|
|
|
|
packetbuf_hdr_len += SICSLOWPAN_HC1_HC_UDP_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
uncomp_hdr_len += UIP_UDPH_LEN;
|
|
|
|
} else {
|
|
|
|
/* HC1 encoding and ttl */
|
2013-12-13 00:09:44 +01:00
|
|
|
PACKETBUF_HC1_PTR[PACKETBUF_HC1_ENCODING] = 0xFA;
|
|
|
|
PACKETBUF_HC1_PTR[PACKETBUF_HC1_TTL] = UIP_IP_BUF->ttl;
|
|
|
|
packetbuf_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif /*UIP_CONF_UDP*/
|
2008-10-14 14:26:18 +02:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/**
|
|
|
|
* \brief Uncompress HC1 (and HC_UDP) headers and put them in
|
|
|
|
* sicslowpan_buf
|
|
|
|
*
|
|
|
|
* This function is called by the input function when the dispatch is
|
2008-10-14 14:26:18 +02:00
|
|
|
* HC1.
|
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
|
|
|
|
*
|
|
|
|
* \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
|
2011-01-04 21:22:21 +01:00
|
|
|
uncompress_hdr_hc1(uint16_t ip_len)
|
2010-11-02 11:56:57 +01:00
|
|
|
{
|
2008-10-14 11:42:33 +02:00
|
|
|
/* version, traffic class, flow label */
|
|
|
|
SICSLOWPAN_IP_BUF->vtc = 0x60;
|
|
|
|
SICSLOWPAN_IP_BUF->tcflow = 0;
|
|
|
|
SICSLOWPAN_IP_BUF->flow = 0;
|
|
|
|
|
|
|
|
/* src and dest ip addresses */
|
|
|
|
uip_ip6addr(&SICSLOWPAN_IP_BUF->srcipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
|
2011-10-27 15:19:21 +02:00
|
|
|
uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->srcipaddr,
|
2010-03-15 17:41:24 +01:00
|
|
|
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
2008-10-14 11:42:33 +02:00
|
|
|
uip_ip6addr(&SICSLOWPAN_IP_BUF->destipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
|
2011-10-27 15:19:21 +02:00
|
|
|
uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->destipaddr,
|
2010-03-15 17:41:24 +01:00
|
|
|
(uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
uncomp_hdr_len += UIP_IPH_LEN;
|
|
|
|
|
|
|
|
/* Next header field */
|
2013-12-13 00:09:44 +01:00
|
|
|
switch(PACKETBUF_HC1_PTR[PACKETBUF_HC1_ENCODING] & 0x06) {
|
2008-10-14 11:42:33 +02:00
|
|
|
case SICSLOWPAN_HC1_NH_ICMP6:
|
|
|
|
SICSLOWPAN_IP_BUF->proto = UIP_PROTO_ICMP6;
|
2013-12-13 00:09:44 +01:00
|
|
|
SICSLOWPAN_IP_BUF->ttl = PACKETBUF_HC1_PTR[PACKETBUF_HC1_TTL];
|
|
|
|
packetbuf_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
#if UIP_CONF_TCP
|
|
|
|
case SICSLOWPAN_HC1_NH_TCP:
|
|
|
|
SICSLOWPAN_IP_BUF->proto = UIP_PROTO_TCP;
|
2013-12-13 00:09:44 +01:00
|
|
|
SICSLOWPAN_IP_BUF->ttl = PACKETBUF_HC1_PTR[PACKETBUF_HC1_TTL];
|
|
|
|
packetbuf_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
break;
|
|
|
|
#endif/* UIP_CONF_TCP */
|
|
|
|
#if UIP_CONF_UDP
|
|
|
|
case SICSLOWPAN_HC1_NH_UDP:
|
|
|
|
SICSLOWPAN_IP_BUF->proto = UIP_PROTO_UDP;
|
2013-12-13 00:09:44 +01:00
|
|
|
if(PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_HC1_ENCODING] & 0x01) {
|
2008-10-14 11:42:33 +02:00
|
|
|
/* UDP header is compressed with HC_UDP */
|
2013-12-13 00:09:44 +01:00
|
|
|
if(PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_UDP_ENCODING] !=
|
2008-10-14 11:42:33 +02:00
|
|
|
SICSLOWPAN_HC_UDP_ALL_C) {
|
|
|
|
PRINTF("sicslowpan (uncompress_hdr), packet not supported");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* IP TTL */
|
2013-12-13 00:09:44 +01:00
|
|
|
SICSLOWPAN_IP_BUF->ttl = PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_TTL];
|
2008-10-14 11:42:33 +02:00
|
|
|
/* UDP ports, len, checksum */
|
2009-04-06 15:11:20 +02:00
|
|
|
SICSLOWPAN_UDP_BUF->srcport =
|
2010-10-19 20:29:03 +02:00
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_PORT_MIN +
|
2013-12-13 00:09:44 +01:00
|
|
|
(PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_PORTS] >> 4));
|
2009-04-06 15:11:20 +02:00
|
|
|
SICSLOWPAN_UDP_BUF->destport =
|
2010-10-19 20:29:03 +02:00
|
|
|
UIP_HTONS(SICSLOWPAN_UDP_PORT_MIN +
|
2013-12-13 00:09:44 +01:00
|
|
|
(PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_PORTS] & 0x0F));
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, &PACKETBUF_HC1_HC_UDP_PTR[PACKETBUF_HC1_HC_UDP_CHKSUM], 2);
|
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 += SICSLOWPAN_HC1_HC_UDP_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif/* UIP_CONF_UDP */
|
|
|
|
default:
|
2008-10-14 14:26:18 +02:00
|
|
|
/* this shouldn't happen, drop */
|
2008-10-14 11:42:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
2013-11-16 14:44:14 +01:00
|
|
|
SICSLOWPAN_IP_BUF->len[0] = len >> 8;
|
|
|
|
SICSLOWPAN_IP_BUF->len[1] = len & 0x00FF;
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
|
|
|
/* This is a 1st fragment */
|
|
|
|
SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
|
|
|
|
SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
|
|
|
|
}
|
|
|
|
/* length field in UDP header */
|
|
|
|
if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) {
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->udplen, &SICSLOWPAN_IP_BUF->len[0], 2);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/** @} */
|
2010-02-25 16:50:58 +01:00
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1 */
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
|
2011-09-02 13:51:09 +02:00
|
|
|
|
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-12-14 23:18:20 +01:00
|
|
|
/* Force acknowledge from sender (test hardware autoacks) */
|
|
|
|
#if SICSLOWPAN_CONF_ACK_ALL
|
|
|
|
packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
|
|
|
|
#endif
|
2011-09-02 13:51:09 +02:00
|
|
|
|
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;
|
2014-02-09 15:02:55 +01: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
|
|
|
|
2012-03-26 23:19:02 +02:00
|
|
|
/* Number of bytes processed. */
|
|
|
|
uint16_t processed_ip_out_len;
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
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_HC1
|
2011-09-02 13:51:09 +02:00
|
|
|
compress_hdr_hc1(&dest);
|
2010-02-25 16:50:58 +01:00
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1 */
|
|
|
|
#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
|
2011-09-02 13:51:09 +02:00
|
|
|
compress_hdr_hc06(&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 */
|
|
|
|
framer_hdrlen = 21;
|
|
|
|
}
|
|
|
|
#else /* USE_FRAMER_HDRLEN */
|
|
|
|
framer_hdrlen = 21;
|
|
|
|
#endif /* USE_FRAMER_HDRLEN */
|
2014-02-09 15:02:55 +01:00
|
|
|
max_payload = MAC_MAX_PAYLOAD - framer_hdrlen - NETSTACK_LLSEC.get_overhead();
|
2013-03-17 23:55:01 +01:00
|
|
|
|
2014-02-09 15:02:55 +01:00
|
|
|
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;
|
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
|
2010-02-25 16:50:58 +01:00
|
|
|
* IPv6/HC1/HC06/HC_UDP dispatchs/headers.
|
2008-10-14 11:42:33 +02:00
|
|
|
* The following fragments contain only the fragn dispatch.
|
|
|
|
*/
|
|
|
|
|
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
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
/* move HC1/HC06/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));
|
2013-12-13 00:09:44 +01:00
|
|
|
/* PACKETBUF_FRAG_BUF->tag = uip_htons(my_tag); */
|
|
|
|
SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_TAG, my_tag);
|
2012-03-26 23:19:02 +02:00
|
|
|
my_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;
|
2014-02-09 15:02:55 +01:00
|
|
|
packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8;
|
2013-12-13 00:09:44 +01:00
|
|
|
PRINTFO("(len %d, tag %d)\n", packetbuf_payload_len, my_tag);
|
|
|
|
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;
|
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));
|
2014-02-09 15:02:55 +01: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;
|
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",
|
2013-12-13 00:09:44 +01:00
|
|
|
processed_ip_out_len >> 3, packetbuf_payload_len, my_tag);
|
|
|
|
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
|
|
|
* \param r The MAC layer
|
|
|
|
*
|
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;
|
2013-07-28 22:32:09 +02:00
|
|
|
uint8_t is_fragment = 0;
|
2008-10-14 11:42:33 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
/* 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
|
|
|
|
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);
|
2008-10-14 11:42:33 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
/* if reassembly timed out, cancel it */
|
2010-11-02 11:56:57 +01:00
|
|
|
if(timer_expired(&reass_timer)) {
|
2008-10-14 11:42:33 +02:00
|
|
|
sicslowpan_len = 0;
|
2012-03-26 23:19:02 +02:00
|
|
|
processed_ip_in_len = 0;
|
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;
|
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
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
if(processed_ip_in_len + packetbuf_datalen() - packetbuf_hdr_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;
|
|
|
|
}
|
|
|
|
|
2013-07-28 22:32:09 +02:00
|
|
|
/* We are currently reassembling a packet, but have just received the first
|
|
|
|
* fragment of another packet. We can either ignore it and hope to receive
|
|
|
|
* the rest of the under-reassembly packet fragments, or we can discard the
|
|
|
|
* previous packet altogether, and start reassembling the new packet.
|
|
|
|
*
|
|
|
|
* We discard the previous packet, and start reassembling the new packet.
|
|
|
|
* This lessens the negative impacts of too high SICSLOWPAN_REASS_MAXAGE.
|
|
|
|
*/
|
|
|
|
#define PRIORITIZE_NEW_PACKETS 1
|
|
|
|
#if PRIORITIZE_NEW_PACKETS
|
2013-11-22 15:12:02 +01:00
|
|
|
|
|
|
|
if(!is_fragment) {
|
|
|
|
/* Prioritize non-fragment packets too. */
|
|
|
|
sicslowpan_len = 0;
|
|
|
|
processed_ip_in_len = 0;
|
|
|
|
} else if(processed_ip_in_len > 0 && first_fragment
|
2013-12-12 23:58:52 +01:00
|
|
|
&& !linkaddr_cmp(&frag_sender, packetbuf_addr(PACKETBUF_ADDR_SENDER))) {
|
2013-07-28 22:32:09 +02:00
|
|
|
sicslowpan_len = 0;
|
|
|
|
processed_ip_in_len = 0;
|
|
|
|
}
|
|
|
|
#endif /* PRIORITIZE_NEW_PACKETS */
|
|
|
|
|
2012-03-26 23:19:02 +02:00
|
|
|
if(processed_ip_in_len > 0) {
|
2008-10-14 11:42:33 +02:00
|
|
|
/* reassembly is ongoing */
|
2010-04-01 12:01:01 +02:00
|
|
|
/* printf("frag %d %d\n", reass_tag, frag_tag);*/
|
2008-10-14 14:26:18 +02:00
|
|
|
if((frag_size > 0 &&
|
2008-10-14 11:42:33 +02:00
|
|
|
(frag_size != sicslowpan_len ||
|
|
|
|
reass_tag != frag_tag ||
|
2013-12-12 23:58:52 +01:00
|
|
|
!linkaddr_cmp(&frag_sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)))) ||
|
2008-10-14 11:42:33 +02:00
|
|
|
frag_size == 0) {
|
|
|
|
/*
|
|
|
|
* the packet is a fragment that does not belong to the packet
|
|
|
|
* being reassembled or the packet is not a fragment.
|
|
|
|
*/
|
2010-02-08 22:59:21 +01:00
|
|
|
PRINTFI("sicslowpan input: Dropping 6lowpan packet that is not a fragment of the packet currently being reassembled\n");
|
2008-10-14 11:42:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2008-10-14 14:26:18 +02:00
|
|
|
/*
|
|
|
|
* reassembly is off
|
|
|
|
* start it if we received a fragment
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
2012-03-26 22:53:57 +02:00
|
|
|
if((frag_size > 0) && (frag_size <= UIP_BUFSIZE)) {
|
2013-07-28 22:32:09 +02:00
|
|
|
/* We are currently not reassembling a packet, but have received a packet fragment
|
|
|
|
* that is not the first one. */
|
|
|
|
if(is_fragment && !first_fragment) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
sicslowpan_len = frag_size;
|
|
|
|
reass_tag = frag_tag;
|
2012-11-26 19:47:11 +01:00
|
|
|
timer_set(&reass_timer, SICSLOWPAN_REASS_MAXAGE * CLOCK_SECOND / 16);
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("sicslowpan input: INIT FRAGMENTATION (len %d, tag %d)\n",
|
2008-10-14 14:26:18 +02:00
|
|
|
sicslowpan_len, reass_tag);
|
2013-12-12 23:58:52 +01:00
|
|
|
linkaddr_copy(&frag_sender, packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
if(packetbuf_hdr_len == SICSLOWPAN_FRAGN_HDR_LEN) {
|
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");
|
|
|
|
uncompress_hdr_hc06(frag_size);
|
|
|
|
} else
|
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
|
2013-12-13 00:09:44 +01:00
|
|
|
switch(PACKETBUF_HC1_PTR[PACKETBUF_HC1_DISPATCH]) {
|
2010-02-25 16:50:58 +01:00
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1
|
2008-10-14 11:42:33 +02:00
|
|
|
case SICSLOWPAN_DISPATCH_HC1:
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("sicslowpan input: HC1\n");
|
2008-10-14 11:42:33 +02:00
|
|
|
uncompress_hdr_hc1(frag_size);
|
|
|
|
break;
|
2010-02-25 16:50:58 +01:00
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1 */
|
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. */
|
2013-12-13 00:09:44 +01:00
|
|
|
memcpy(SICSLOWPAN_IP_BUF, 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#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;
|
2013-03-17 23:55:01 +01:00
|
|
|
if(req_size > sizeof(sicslowpan_buf)) {
|
|
|
|
PRINTF(
|
|
|
|
"SICSLOWPAN: packet dropped, minimum required SICSLOWPAN_IP_BUF size: %d+%d+%d+%d=%d (current size: %d)\n",
|
|
|
|
UIP_LLH_LEN, uncomp_hdr_len, (uint16_t)(frag_offset << 3),
|
2013-12-13 00:09:44 +01:00
|
|
|
packetbuf_payload_len, req_size, sizeof(sicslowpan_buf));
|
2013-03-17 23:55:01 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-13 00:09:44 +01:00
|
|
|
memcpy((uint8_t *)SICSLOWPAN_IP_BUF + uncomp_hdr_len + (uint16_t)(frag_offset << 3), packetbuf_ptr + packetbuf_hdr_len, packetbuf_payload_len);
|
2008-10-14 11:42:33 +02: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) {
|
2012-03-26 23:19:02 +02:00
|
|
|
processed_ip_in_len += uncomp_hdr_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) {
|
2012-03-26 23:19:02 +02:00
|
|
|
processed_ip_in_len = frag_size;
|
2011-09-05 14:26:48 +02:00
|
|
|
} else {
|
2013-12-13 00:09:44 +01:00
|
|
|
processed_ip_in_len += packetbuf_payload_len;
|
2011-09-05 14:26:48 +02:00
|
|
|
}
|
2013-12-13 00:09:44 +01:00
|
|
|
PRINTF("processed_ip_in_len %d, packetbuf_payload_len %d\n", processed_ip_in_len, packetbuf_payload_len);
|
2011-09-05 14:26:48 +02:00
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
} else {
|
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
2013-12-13 00:09:44 +01:00
|
|
|
sicslowpan_len = packetbuf_payload_len + uncomp_hdr_len;
|
2008-10-14 11:42:33 +02:00
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have a full IP packet in sicslowpan_buf, deliver it to
|
|
|
|
* the IP stack
|
|
|
|
*/
|
2012-03-26 23:19:02 +02:00
|
|
|
PRINTF("sicslowpan_init processed_ip_in_len %d, sicslowpan_len %d\n",
|
|
|
|
processed_ip_in_len, sicslowpan_len);
|
|
|
|
if(processed_ip_in_len == 0 || (processed_ip_in_len == sicslowpan_len)) {
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFI("sicslowpan input: IP packet ready (length %d)\n",
|
2008-10-14 11:42:33 +02:00
|
|
|
sicslowpan_len);
|
2011-01-04 21:22:21 +01:00
|
|
|
memcpy((uint8_t *)UIP_IP_BUF, (uint8_t *)SICSLOWPAN_IP_BUF, sicslowpan_len);
|
2008-10-14 11:42:33 +02:00
|
|
|
uip_len = sicslowpan_len;
|
|
|
|
sicslowpan_len = 0;
|
2012-03-26 23:19:02 +02:00
|
|
|
processed_ip_in_len = 0;
|
2008-10-14 11:42:33 +02:00
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
2009-11-02 12:58:56 +01:00
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#if DEBUG
|
|
|
|
{
|
2011-10-27 17:13:26 +02:00
|
|
|
uint16_t ndx;
|
|
|
|
PRINTF("after decompression %u:", SICSLOWPAN_IP_BUF->len[1]);
|
|
|
|
for (ndx = 0; ndx < SICSLOWPAN_IP_BUF->len[1] + 40; ndx++) {
|
|
|
|
uint8_t data = ((uint8_t *) (SICSLOWPAN_IP_BUF))[ndx];
|
|
|
|
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
|
|
|
*/
|
|
|
|
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;}
|
|
|
|
*/
|
2010-03-19 09:15:20 +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
|
|
|
|
SICSLOWPAN_CONF_ADDR_CONTEXT_0;
|
|
|
|
#else
|
2010-02-25 16:50:58 +01:00
|
|
|
addr_contexts[0].prefix[0] = 0xaa;
|
|
|
|
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
|
|
|
|
if (i==1) {
|
|
|
|
addr_contexts[1].used = 1;
|
|
|
|
addr_contexts[1].number = 1;
|
|
|
|
SICSLOWPAN_CONF_ADDR_CONTEXT_1;
|
|
|
|
#ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
|
|
|
|
} else if (i==2) {
|
|
|
|
addr_contexts[2].used = 1;
|
|
|
|
addr_contexts[2].number = 2;
|
|
|
|
SICSLOWPAN_CONF_ADDR_CONTEXT_2;
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
addr_contexts[i].used = 0;
|
|
|
|
}
|
|
|
|
#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
|
|
|
/** @} */
|
2013-03-17 23:21:30 +01:00
|
|
|
#endif /* UIP_CONF_IPV6 */
|