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.
|
|
|
|
*
|
2010-06-01 14:37:54 +02:00
|
|
|
* $Id: sicslowpan.c,v 1.43 2010/06/01 12:37:54 joxe Exp $
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* \file
|
2010-02-25 16:50:58 +01:00
|
|
|
* 6lowpan implementation (RFC4944 and draft-ietf-6lowpan-hc-06)
|
2008-10-14 11:42:33 +02:00
|
|
|
*
|
|
|
|
* \author Adam Dunkels <adam@sics.se>
|
|
|
|
* \author Nicolas Tsiftes <nvt@sics.se>
|
|
|
|
* \author Niclas Finne <nfi@sics.se>
|
|
|
|
* \author Mathilde Durvy <mdurvy@cisco.com>
|
|
|
|
* \author Julien Abeille <jabeille@cisco.com>
|
2010-02-25 16:50:58 +01:00
|
|
|
* \author Joakim Eriksson <joakime@sics.se>
|
2010-03-26 11:28:51 +01:00
|
|
|
* \author Joel Hoglund <joel@sics.se>
|
2008-10-14 11:42:33 +02:00
|
|
|
*/
|
|
|
|
|
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"
|
2008-10-14 11:42:33 +02:00
|
|
|
#include "net/tcpip.h"
|
|
|
|
#include "net/uip.h"
|
2010-03-15 17:41:24 +01:00
|
|
|
#include "net/uip-ds6.h"
|
2008-10-14 11:42:33 +02:00
|
|
|
#include "net/rime.h"
|
|
|
|
#include "net/sicslowpan.h"
|
2010-03-12 14:40:13 +01:00
|
|
|
#include "net/neighbor-info.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
|
|
|
|
|
|
|
#define DEBUG 0
|
|
|
|
#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 */
|
2008-10-14 11:42:33 +02:00
|
|
|
u8_t p;
|
|
|
|
#include <stdio.h>
|
|
|
|
#define PRINTF(...) printf(__VA_ARGS__)
|
2009-07-10 15:33:45 +02:00
|
|
|
#define PRINTFI(...) printf(__VA_ARGS__)
|
|
|
|
#define PRINTFO(...) printf(__VA_ARGS__)
|
2008-10-14 11:42:33 +02:00
|
|
|
#define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
|
|
|
|
#define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5],lladdr->addr[6], lladdr->addr[7])
|
2009-03-12 22:58:20 +01:00
|
|
|
#define PRINTPACKETBUF() PRINTF("RIME buffer: "); for(p = 0; p < packetbuf_datalen(); p++){PRINTF("%.2X", *(rime_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
|
|
|
|
#define PRINTF(...)
|
2009-07-10 15:33:45 +02:00
|
|
|
#define PRINTFI(...)
|
|
|
|
#define PRINTFO(...)
|
2008-10-14 11:42:33 +02:00
|
|
|
#define PRINT6ADDR(addr)
|
|
|
|
#define PRINTLLADDR(lladdr)
|
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-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 */
|
|
|
|
|
2010-05-11 12:02:29 +02:00
|
|
|
#ifndef SICSLOWPAN_CONF_NEIGHBOR_INFO
|
|
|
|
/* Default is to use neighbor info updates if using RPL */
|
|
|
|
#define SICSLOWPAN_CONF_NEIGHBOR_INFO UIP_CONF_IPV6_RPL
|
|
|
|
#endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */
|
|
|
|
|
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)
|
|
|
|
|
2008-10-14 11:42:33 +02:00
|
|
|
/** \name Pointers in the rime buffer
|
|
|
|
* @{
|
|
|
|
*/
|
2009-04-06 15:11:20 +02:00
|
|
|
#define RIME_FRAG_PTR (rime_ptr)
|
|
|
|
#define RIME_FRAG_DISPATCH_SIZE 0 /* 16 bit */
|
|
|
|
#define RIME_FRAG_TAG 2 /* 16 bit */
|
|
|
|
#define RIME_FRAG_OFFSET 4 /* 8 bit */
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
/* define the buffer as a byte array */
|
|
|
|
#define RIME_IPHC_BUF ((uint8_t *)(rime_ptr + rime_hdr_len))
|
|
|
|
|
2009-04-06 15:11:20 +02:00
|
|
|
#define RIME_HC1_PTR (rime_ptr + rime_hdr_len)
|
|
|
|
#define RIME_HC1_DISPATCH 0 /* 8 bit */
|
|
|
|
#define RIME_HC1_ENCODING 1 /* 8 bit */
|
|
|
|
#define RIME_HC1_TTL 2 /* 8 bit */
|
|
|
|
|
|
|
|
#define RIME_HC1_HC_UDP_PTR (rime_ptr + rime_hdr_len)
|
|
|
|
#define RIME_HC1_HC_UDP_DISPATCH 0 /* 8 bit */
|
|
|
|
#define RIME_HC1_HC_UDP_HC1_ENCODING 1 /* 8 bit */
|
|
|
|
#define RIME_HC1_HC_UDP_UDP_ENCODING 2 /* 8 bit */
|
|
|
|
#define RIME_HC1_HC_UDP_TTL 3 /* 8 bit */
|
|
|
|
#define RIME_HC1_HC_UDP_PORTS 4 /* 8 bit */
|
2009-04-06 17:54:07 +02:00
|
|
|
#define RIME_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])
|
2008-10-14 11:42:33 +02:00
|
|
|
/** @} */
|
|
|
|
|
|
|
|
|
|
|
|
/** \brief Size of the 802.15.4 payload (127byte - 25 for MAC header) */
|
|
|
|
#define MAC_MAX_PAYLOAD 102
|
|
|
|
|
|
|
|
/** \name General variables
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
/** A pointer to the mac driver */
|
2010-01-28 14:50:51 +01:00
|
|
|
const struct mac_driver *sicslowpan_mac;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
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
|
|
|
/**
|
|
|
|
* A pointer to the rime buffer.
|
|
|
|
* We initialize it to the beginning of the rime buffer, then
|
2008-10-14 11:42:33 +02:00
|
|
|
* access different fields by updating the offset rime_hdr_len.
|
|
|
|
*/
|
|
|
|
static u8_t *rime_ptr;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* rime_hdr_len is the total length of (the processed) 6lowpan headers
|
|
|
|
* (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
|
|
|
*/
|
|
|
|
static u8_t rime_hdr_len;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The length of the payload in the Rime 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
|
|
|
*/
|
|
|
|
static u8_t rime_payload_len;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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).
|
|
|
|
*/
|
|
|
|
static u8_t uncomp_hdr_len;
|
|
|
|
/** @} */
|
|
|
|
|
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
/** \name Fragmentation related variables
|
|
|
|
* @{
|
|
|
|
*/
|
2010-02-25 16:50:58 +01:00
|
|
|
|
|
|
|
static u16_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.
|
|
|
|
*/
|
|
|
|
static u16_t processed_ip_len;
|
|
|
|
|
|
|
|
/** Datagram tag to be put in the fragments I send. */
|
|
|
|
static u16_t my_tag;
|
|
|
|
|
|
|
|
/** When reassembling, the tag in the fragments being merged. */
|
|
|
|
static u16_t reass_tag;
|
|
|
|
|
|
|
|
/** When reassembling, the source address of the fragments being merged */
|
|
|
|
rimeaddr_t frag_sender;
|
|
|
|
|
|
|
|
/** 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 */
|
|
|
|
|
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-05-31 22:42:27 +02:00
|
|
|
/* Uncompression of linklocal and other */
|
|
|
|
/* 0 -> 16 bits from packet */
|
|
|
|
/* 1 -> 2 bits from prefix - bunch of zeroes and 8 from packet */
|
|
|
|
/* 2 -> 2 bits from prefix - zeroes + 2 from packet */
|
|
|
|
/* 3 -> 2 bits from prefix - infer 8 bytes from lladdr */
|
|
|
|
/* NOTE: => the uncompress function does change 0xf to 0x10 */
|
|
|
|
const uint8_t unc_llconf[] = {0x0f,0x28,0x22,0x20};
|
|
|
|
const uint8_t unc_ctxconf[] = {0x0f,0x88,0x82,0x80};
|
|
|
|
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*
|
2008-10-14 11:42:33 +02: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*
|
2008-10-14 11:42:33 +02:00
|
|
|
addr_context_lookup_by_number(u8_t number) {
|
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-03-16 11:21:04 +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-03-16 11:21:04 +01:00
|
|
|
} else if(sicslowpan_is_iid_16_bit_compressable(ipaddr)){
|
|
|
|
/* compress IID to 16 bits xxxx::XXXX */
|
|
|
|
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[],
|
|
|
|
uint8_t pref_post_count, uip_lladdr_t *lladdr) {
|
|
|
|
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);
|
|
|
|
hc06_ptr += postcount;
|
|
|
|
} else {
|
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.
|
|
|
|
* \param rime_destaddr L2 destination address, needed to compress IP
|
|
|
|
* dest
|
|
|
|
*/
|
|
|
|
static void
|
2010-02-25 16:50:58 +01:00
|
|
|
compress_hdr_hc06(rimeaddr_t *rime_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
|
|
|
|
PRINTF("before compression: ");
|
|
|
|
for (tmp = 0; tmp < UIP_IP_BUF->len[1] + 40; tmp++) {
|
|
|
|
uint8_t data = ((uint8_t *) (UIP_IP_BUF))[tmp];
|
|
|
|
PRINTF("%02x", data);
|
|
|
|
}
|
|
|
|
PRINTF("\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
hc06_ptr = rime_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;
|
2010-02-25 16:50:58 +01:00
|
|
|
RIME_IPHC_BUF[2] = 0; /* might not be used - but needs to be cleared */
|
|
|
|
|
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 */
|
|
|
|
#if UIP_CONF_UDP
|
|
|
|
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;
|
2010-02-25 16:50:58 +01:00
|
|
|
RIME_IPHC_BUF[2] |= context->number << 4;
|
|
|
|
/* 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 */
|
|
|
|
} else if(uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) {
|
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;
|
|
|
|
} 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;
|
|
|
|
} 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;
|
2010-02-25 16:50:58 +01:00
|
|
|
RIME_IPHC_BUF[2] |= context->number;
|
|
|
|
/* 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,
|
|
|
|
&UIP_IP_BUF->destipaddr, (uip_lladdr_t *)rime_destaddr);
|
2010-02-25 16:50:58 +01:00
|
|
|
/* No context found for this address */
|
|
|
|
} else if(uip_is_addr_link_local(&UIP_IP_BUF->destipaddr)) {
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
|
|
|
|
&UIP_IP_BUF->destipaddr, (uip_lladdr_t *)rime_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;
|
|
|
|
|
|
|
|
#if UIP_CONF_UDP
|
|
|
|
/* 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",
|
|
|
|
HTONS(UIP_UDP_BUF->srcport), HTONS(UIP_UDP_BUF->destport));
|
|
|
|
/* Mask out the last 4 bits can be used as a mask */
|
|
|
|
if(((HTONS(UIP_UDP_BUF->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
|
|
|
|
((HTONS(UIP_UDP_BUF->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
|
|
|
|
/* 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) =
|
|
|
|
(u8_t)((HTONS(UIP_UDP_BUF->srcport) -
|
|
|
|
SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
|
|
|
|
(u8_t)((HTONS(UIP_UDP_BUF->destport) -
|
|
|
|
SICSLOWPAN_UDP_4_BIT_PORT_MIN));
|
|
|
|
hc06_ptr += 2;
|
|
|
|
} else if((HTONS(UIP_UDP_BUF->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
|
|
|
|
/* 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) =
|
|
|
|
(u8_t)((HTONS(UIP_UDP_BUF->destport) -
|
|
|
|
SICSLOWPAN_UDP_8_BIT_PORT_MIN));
|
|
|
|
hc06_ptr += 4;
|
|
|
|
} else if((HTONS(UIP_UDP_BUF->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
|
|
|
|
/* 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) =
|
2010-03-26 11:28:51 +01:00
|
|
|
(u8_t)((HTONS(UIP_UDP_BUF->srcport) -
|
|
|
|
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
|
|
|
|
|
|
|
/* before the rime_hdr_len operation */
|
|
|
|
RIME_IPHC_BUF[0] = iphc0;
|
|
|
|
RIME_IPHC_BUF[1] = iphc1;
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
rime_hdr_len = hc06_ptr - rime_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.
|
2008-10-14 11:42:33 +02:00
|
|
|
* We %process the packet in the rime buffer, uncompress the header
|
|
|
|
* fields, and copy the result in the sicslowpan buffer.
|
|
|
|
* At the end of the decompression, rime_hdr_len and uncompressed_hdr_len
|
|
|
|
* 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
|
2010-02-25 16:50:58 +01:00
|
|
|
uncompress_hdr_hc06(u16_t ip_len) {
|
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 */
|
|
|
|
hc06_ptr = rime_ptr + rime_hdr_len + 2;
|
|
|
|
|
2010-05-24 16:28:56 +02:00
|
|
|
iphc0 = RIME_IPHC_BUF[0];
|
|
|
|
iphc1 = RIME_IPHC_BUF[1];
|
|
|
|
|
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;
|
|
|
|
hc06_ptr += 3;
|
|
|
|
} 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) ?
|
2010-02-25 16:50:58 +01:00
|
|
|
RIME_IPHC_BUF[2] >> 4 : 0;
|
|
|
|
|
|
|
|
/* Source address */
|
2010-05-24 16:28:56 +02:00
|
|
|
if((iphc1 & SICSLOWPAN_IPHC_SAM_11) != SICSLOWPAN_IPHC_SAM_00) {
|
2010-02-25 16:50:58 +01:00
|
|
|
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
|
|
|
} else {
|
|
|
|
PRINTF("IPHC: found compressed source context for sci = %d\n", sci);
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
2010-02-25 16:50:58 +01:00
|
|
|
}
|
2010-05-31 22:42:27 +02:00
|
|
|
uncompress_addr(&SICSLOWPAN_IP_BUF->srcipaddr, context->prefix,
|
|
|
|
unc_ctxconf[tmp],
|
|
|
|
(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) ?
|
2010-02-25 16:50:58 +01:00
|
|
|
RIME_IPHC_BUF[2] & 0x0f : 0;
|
|
|
|
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",
|
|
|
|
HTONS(SICSLOWPAN_UDP_BUF->srcport), HTONS(SICSLOWPAN_UDP_BUF->destport));
|
|
|
|
hc06_ptr += 5;
|
|
|
|
break;
|
2010-02-25 16:50:58 +01:00
|
|
|
|
2010-03-26 11:28:51 +01:00
|
|
|
case SICSLOWPAN_NHC_UDP_CS_P_01:
|
2010-05-31 22:42:27 +02:00
|
|
|
/* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
|
2010-03-26 11:28:51 +01:00
|
|
|
PRINTF("IPHC: Decompressing destination\n");
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
|
|
|
|
SICSLOWPAN_UDP_BUF->destport = HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
|
|
|
HTONS(SICSLOWPAN_UDP_BUF->srcport), HTONS(SICSLOWPAN_UDP_BUF->destport));
|
|
|
|
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");
|
|
|
|
SICSLOWPAN_UDP_BUF->srcport = HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
|
|
|
|
(*(hc06_ptr + 1)));
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 2, 2);
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
|
|
|
|
HTONS(SICSLOWPAN_UDP_BUF->srcport), HTONS(SICSLOWPAN_UDP_BUF->destport));
|
|
|
|
hc06_ptr += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SICSLOWPAN_NHC_UDP_CS_P_11:
|
|
|
|
/* 1 byte for NHC, 1 byte for ports */
|
|
|
|
SICSLOWPAN_UDP_BUF->srcport = HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
|
|
|
(*(hc06_ptr + 1) >> 4));
|
|
|
|
SICSLOWPAN_UDP_BUF->destport = HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
|
|
|
|
((*(hc06_ptr + 1)) & 0x0F));
|
|
|
|
PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
|
|
|
|
HTONS(SICSLOWPAN_UDP_BUF->srcport), HTONS(SICSLOWPAN_UDP_BUF->destport));
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
rime_hdr_len = hc06_ptr - rime_ptr;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* IP length field. */
|
|
|
|
if(ip_len == 0) {
|
|
|
|
/* This is not a fragmented packet */
|
|
|
|
SICSLOWPAN_IP_BUF->len[0] = 0;
|
2009-03-12 22:58:20 +01:00
|
|
|
SICSLOWPAN_IP_BUF->len[1] = packetbuf_datalen() - rime_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
|
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
|
|
|
|
*
|
|
|
|
* \param rime_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
|
|
|
|
compress_hdr_hc1(rimeaddr_t *rime_destaddr)
|
|
|
|
{
|
|
|
|
/*
|
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,
|
|
|
|
(uip_lladdr_t *)rime_destaddr) ||
|
|
|
|
(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,
|
2008-10-14 11:42:33 +02:00
|
|
|
* compress nothing, copy IPv6 header in rime buffer
|
2008-10-14 14:26:18 +02:00
|
|
|
*/
|
2008-10-14 11:42:33 +02:00
|
|
|
*rime_ptr = SICSLOWPAN_DISPATCH_IPV6;
|
|
|
|
rime_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
|
|
|
|
memcpy(rime_ptr + rime_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
|
|
|
|
rime_hdr_len += UIP_IPH_LEN;
|
|
|
|
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
|
|
|
|
*/
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_HC1_PTR[RIME_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 */
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_HC1_PTR[RIME_HC1_ENCODING] = 0xFC;
|
|
|
|
RIME_HC1_PTR[RIME_HC1_TTL] = UIP_IP_BUF->ttl;
|
2008-10-14 11:42:33 +02:00
|
|
|
rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
|
|
|
break;
|
|
|
|
#if UIP_CONF_TCP
|
|
|
|
case UIP_PROTO_TCP:
|
|
|
|
/* HC1 encoding and ttl */
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_HC1_PTR[RIME_HC1_ENCODING] = 0xFE;
|
|
|
|
RIME_HC1_PTR[RIME_HC1_TTL] = UIP_IP_BUF->ttl;
|
2008-10-14 11:42:33 +02:00
|
|
|
rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
|
|
|
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);
|
|
|
|
if(HTONS(UIP_UDP_BUF->srcport) >= SICSLOWPAN_UDP_PORT_MIN &&
|
|
|
|
HTONS(UIP_UDP_BUF->srcport) < SICSLOWPAN_UDP_PORT_MAX &&
|
|
|
|
HTONS(UIP_UDP_BUF->destport) >= SICSLOWPAN_UDP_PORT_MIN &&
|
|
|
|
HTONS(UIP_UDP_BUF->destport) < SICSLOWPAN_UDP_PORT_MAX) {
|
|
|
|
/* HC1 encoding */
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_HC1_ENCODING] = 0xFB;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* HC_UDP encoding, ttl, src and dest ports, checksum */
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_UDP_ENCODING] = 0xE0;
|
|
|
|
RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_TTL] = UIP_IP_BUF->ttl;
|
2010-05-24 16:28:56 +02:00
|
|
|
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_PORTS] =
|
|
|
|
(u8_t)((HTONS(UIP_UDP_BUF->srcport) -
|
|
|
|
SICSLOWPAN_UDP_PORT_MIN) << 4) +
|
|
|
|
(u8_t)((HTONS(UIP_UDP_BUF->destport) - SICSLOWPAN_UDP_PORT_MIN));
|
|
|
|
memcpy(&RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_CHKSUM], &UIP_UDP_BUF->udpchksum, 2);
|
2008-10-14 11:42:33 +02:00
|
|
|
rime_hdr_len += SICSLOWPAN_HC1_HC_UDP_HDR_LEN;
|
|
|
|
uncomp_hdr_len += UIP_UDPH_LEN;
|
|
|
|
} else {
|
|
|
|
/* HC1 encoding and ttl */
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_HC1_PTR[RIME_HC1_ENCODING] = 0xFA;
|
|
|
|
RIME_HC1_PTR[RIME_HC1_TTL] = UIP_IP_BUF->ttl;
|
2008-10-14 11:42:33 +02:00
|
|
|
rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
|
|
|
}
|
|
|
|
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.
|
2008-10-14 11:42:33 +02:00
|
|
|
* We %process the packet in the rime buffer, uncompress the header
|
|
|
|
* fields, and copy the result in the sicslowpan buffer.
|
|
|
|
* At the end of the decompression, rime_hdr_len and uncompressed_hdr_len
|
|
|
|
* 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
|
|
|
|
uncompress_hdr_hc1(u16_t ip_len) {
|
|
|
|
/* 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);
|
2010-03-15 17:41:24 +01:00
|
|
|
uip_sd6_set_addr_iid(&SICSLOWPAN_IP_BUF->srcipaddr,
|
|
|
|
(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);
|
2010-03-15 17:41:24 +01:00
|
|
|
uip_sd6_set_addr_iid(&SICSLOWPAN_IP_BUF->destipaddr,
|
|
|
|
(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 */
|
2009-04-06 15:11:20 +02:00
|
|
|
switch(RIME_HC1_PTR[RIME_HC1_ENCODING] & 0x06) {
|
2008-10-14 11:42:33 +02:00
|
|
|
case SICSLOWPAN_HC1_NH_ICMP6:
|
|
|
|
SICSLOWPAN_IP_BUF->proto = UIP_PROTO_ICMP6;
|
2009-04-06 15:11:20 +02:00
|
|
|
SICSLOWPAN_IP_BUF->ttl = RIME_HC1_PTR[RIME_HC1_TTL];
|
2008-10-14 11:42:33 +02:00
|
|
|
rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
|
|
|
break;
|
|
|
|
#if UIP_CONF_TCP
|
|
|
|
case SICSLOWPAN_HC1_NH_TCP:
|
|
|
|
SICSLOWPAN_IP_BUF->proto = UIP_PROTO_TCP;
|
2009-04-06 15:11:20 +02:00
|
|
|
SICSLOWPAN_IP_BUF->ttl = RIME_HC1_PTR[RIME_HC1_TTL];
|
2008-10-14 11:42:33 +02:00
|
|
|
rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
|
|
|
break;
|
|
|
|
#endif/* UIP_CONF_TCP */
|
|
|
|
#if UIP_CONF_UDP
|
|
|
|
case SICSLOWPAN_HC1_NH_UDP:
|
|
|
|
SICSLOWPAN_IP_BUF->proto = UIP_PROTO_UDP;
|
2009-04-06 15:11:20 +02:00
|
|
|
if(RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_HC1_ENCODING] & 0x01) {
|
2008-10-14 11:42:33 +02:00
|
|
|
/* UDP header is compressed with HC_UDP */
|
2009-04-06 15:11:20 +02:00
|
|
|
if(RIME_HC1_HC_UDP_PTR[RIME_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 */
|
2009-04-06 15:11:20 +02:00
|
|
|
SICSLOWPAN_IP_BUF->ttl = RIME_HC1_HC_UDP_PTR[RIME_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 =
|
|
|
|
HTONS(SICSLOWPAN_UDP_PORT_MIN +
|
|
|
|
(RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_PORTS] >> 4));
|
|
|
|
SICSLOWPAN_UDP_BUF->destport =
|
|
|
|
HTONS(SICSLOWPAN_UDP_PORT_MIN +
|
|
|
|
(RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_PORTS] & 0x0F));
|
|
|
|
memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, &RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_CHKSUM], 2);
|
2008-10-14 11:42:33 +02:00
|
|
|
uncomp_hdr_len += UIP_UDPH_LEN;
|
|
|
|
rime_hdr_len += SICSLOWPAN_HC1_HC_UDP_HDR_LEN;
|
|
|
|
} else {
|
|
|
|
rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
|
|
|
|
}
|
|
|
|
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) {
|
|
|
|
/* This is not a fragmented packet */
|
|
|
|
SICSLOWPAN_IP_BUF->len[0] = 0;
|
2009-03-12 22:58:20 +01:00
|
|
|
SICSLOWPAN_IP_BUF->len[1] = packetbuf_datalen() - rime_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
|
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
|
|
|
|
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
|
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
|
|
|
|
compress_hdr_ipv6(rimeaddr_t *rime_destaddr) {
|
|
|
|
*rime_ptr = SICSLOWPAN_DISPATCH_IPV6;
|
|
|
|
rime_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
|
|
|
|
memcpy(rime_ptr + rime_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
|
|
|
|
rime_hdr_len += UIP_IPH_LEN;
|
|
|
|
uncomp_hdr_len += UIP_IPH_LEN;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/** @} */
|
2010-02-25 16:50:58 +01:00
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*--------------------------------------------------------------------*/
|
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)
|
|
|
|
{
|
|
|
|
#if SICSLOWPAN_CONF_NEIGHBOR_INFO
|
|
|
|
neighbor_info_packet_sent(status, transmissions);
|
|
|
|
#endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */
|
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
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
|
|
|
|
send_packet(rimeaddr_t *dest)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
2010-03-12 14:20:13 +01:00
|
|
|
/* Provide a callback function to receive the result of
|
|
|
|
a packet transmission. */
|
|
|
|
NETSTACK_MAC.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
|
|
|
}
|
|
|
|
|
|
|
|
/** \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.
|
|
|
|
*/
|
|
|
|
static u8_t
|
|
|
|
output(uip_lladdr_t *localdest)
|
|
|
|
{
|
|
|
|
/* The MAC address of the destination of the packet */
|
2008-10-14 14:26:18 +02:00
|
|
|
rimeaddr_t dest;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
|
|
|
|
/* init */
|
|
|
|
uncomp_hdr_len = 0;
|
|
|
|
rime_hdr_len = 0;
|
|
|
|
|
|
|
|
/* reset rime buffer */
|
2009-03-12 22:58:20 +01:00
|
|
|
packetbuf_clear();
|
|
|
|
rime_ptr = packetbuf_dataptr();
|
2009-11-02 12:58:56 +01:00
|
|
|
|
2010-03-26 13:29:29 +01:00
|
|
|
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, 3);
|
2010-04-01 12:01:01 +02:00
|
|
|
|
2010-04-01 12:56:00 +02:00
|
|
|
#define TCP_FIN 0x01
|
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 &&
|
|
|
|
(UIP_TCP_BUF->flags & TCP_FIN) == 0) {
|
|
|
|
packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
|
|
|
|
PACKETBUF_ATTR_PACKET_TYPE_STREAM);
|
2009-11-02 12:58:56 +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) {
|
|
|
|
rimeaddr_copy(&dest, &rimeaddr_null);
|
|
|
|
} else {
|
|
|
|
rimeaddr_copy(&dest, (const rimeaddr_t *)localdest);
|
|
|
|
}
|
|
|
|
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("sicslowpan output: sending packet len %d\n", uip_len);
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* Try to compress the headers */
|
2010-02-25 16:50:58 +01:00
|
|
|
#if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1
|
2008-10-14 11:42:33 +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
|
2008-10-14 11:42:33 +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
|
|
|
|
compress_hdr_hc06(&dest);
|
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("sicslowpan output: header of len %d\n", rime_hdr_len);
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
if(uip_len - uncomp_hdr_len > MAC_MAX_PAYLOAD - rime_hdr_len) {
|
|
|
|
#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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* 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 */
|
2008-10-14 11:42:33 +02:00
|
|
|
memmove(rime_ptr + SICSLOWPAN_FRAG1_HDR_LEN, rime_ptr, rime_hdr_len);
|
|
|
|
|
|
|
|
/*
|
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
|
|
|
*/
|
2009-04-06 15:11:20 +02:00
|
|
|
/* RIME_FRAG_BUF->dispatch_size = */
|
|
|
|
/* htons((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len); */
|
|
|
|
SET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE,
|
|
|
|
((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len));
|
|
|
|
/* RIME_FRAG_BUF->tag = htons(my_tag); */
|
|
|
|
SET16(RIME_FRAG_PTR, RIME_FRAG_TAG, my_tag);
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* Copy payload and send */
|
|
|
|
rime_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
|
|
|
|
rime_payload_len = (MAC_MAX_PAYLOAD - rime_hdr_len) & 0xf8;
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("(len %d, tag %d)\n", rime_payload_len, my_tag);
|
2008-10-14 11:42:33 +02:00
|
|
|
memcpy(rime_ptr + rime_hdr_len,
|
|
|
|
(void *)UIP_IP_BUF + uncomp_hdr_len, rime_payload_len);
|
2009-03-12 22:58:20 +01:00
|
|
|
packetbuf_set_datalen(rime_payload_len + rime_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
|
|
|
|
|
|
|
/* set processed_ip_len to what we already sent from the IP payload*/
|
|
|
|
processed_ip_len = rime_payload_len + uncomp_hdr_len;
|
|
|
|
|
|
|
|
/*
|
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
|
|
|
|
*/
|
|
|
|
rime_hdr_len = SICSLOWPAN_FRAGN_HDR_LEN;
|
2009-04-06 15:11:20 +02:00
|
|
|
/* RIME_FRAG_BUF->dispatch_size = */
|
|
|
|
/* htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */
|
|
|
|
SET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE,
|
|
|
|
((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
|
2008-10-14 11:42:33 +02:00
|
|
|
rime_payload_len = (MAC_MAX_PAYLOAD - rime_hdr_len) & 0xf8;
|
|
|
|
while(processed_ip_len < uip_len){
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("sicslowpan output: fragment ");
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_FRAG_PTR[RIME_FRAG_OFFSET] = processed_ip_len >> 3;
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* Copy payload and send */
|
|
|
|
if(uip_len - processed_ip_len < rime_payload_len){
|
|
|
|
/* last fragment */
|
|
|
|
rime_payload_len = uip_len - processed_ip_len;
|
|
|
|
}
|
2009-07-10 15:33:45 +02:00
|
|
|
PRINTFO("(offset %d, len %d, tag %d)\n",
|
2008-10-14 11:42:33 +02:00
|
|
|
processed_ip_len >> 3, rime_payload_len, my_tag);
|
|
|
|
memcpy(rime_ptr + rime_hdr_len,
|
|
|
|
(void *)UIP_IP_BUF + processed_ip_len, rime_payload_len);
|
2009-03-12 22:58:20 +01:00
|
|
|
packetbuf_set_datalen(rime_payload_len + rime_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;
|
2008-10-14 11:42:33 +02:00
|
|
|
processed_ip_len += rime_payload_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* end: reset global variables */
|
|
|
|
my_tag++;
|
|
|
|
processed_ip_len = 0;
|
|
|
|
#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 {
|
2008-10-14 11:42:33 +02:00
|
|
|
/*
|
|
|
|
* The packet does not need to be fragmented
|
|
|
|
* copy "payload" and send
|
|
|
|
*/
|
|
|
|
memcpy(rime_ptr + rime_hdr_len, (void *)UIP_IP_BUF + uncomp_hdr_len,
|
|
|
|
uip_len - uncomp_hdr_len);
|
2009-03-12 22:58:20 +01:00
|
|
|
packetbuf_set_datalen(uip_len - uncomp_hdr_len + rime_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) */
|
|
|
|
u16_t frag_size = 0;
|
|
|
|
/* offset of the fragment in the IP packet */
|
|
|
|
u8_t frag_offset = 0;
|
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
/* tag of the fragment */
|
|
|
|
u16_t frag_tag = 0;
|
|
|
|
#endif /*SICSLOWPAN_CONF_FRAG*/
|
|
|
|
|
|
|
|
/* init */
|
|
|
|
uncomp_hdr_len = 0;
|
|
|
|
rime_hdr_len = 0;
|
|
|
|
|
|
|
|
/* The MAC puts the 15.4 payload inside the RIME data buffer */
|
2009-03-12 22:58:20 +01:00
|
|
|
rime_ptr = packetbuf_dataptr();
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
/* if reassembly timed out, cancel it */
|
|
|
|
if(timer_expired(&reass_timer)){
|
|
|
|
sicslowpan_len = 0;
|
2008-10-14 14:26:18 +02:00
|
|
|
processed_ip_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
|
|
|
*/
|
2009-04-06 15:11:20 +02:00
|
|
|
switch((GET16(RIME_FRAG_PTR, RIME_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;
|
2009-04-06 15:11:20 +02:00
|
|
|
/* frag_size = (ntohs(RIME_FRAG_BUF->dispatch_size) & 0x07ff); */
|
|
|
|
frag_size = GET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
|
|
|
|
/* frag_tag = ntohs(RIME_FRAG_BUF->tag); */
|
|
|
|
frag_tag = GET16(RIME_FRAG_PTR, RIME_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);
|
2008-10-14 14:26:18 +02:00
|
|
|
rime_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
|
2010-04-01 12:01:01 +02:00
|
|
|
/* printf("frag1 %d %d\n", reass_tag, frag_tag);*/
|
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 ");
|
2009-04-06 15:11:20 +02:00
|
|
|
frag_offset = RIME_FRAG_PTR[RIME_FRAG_OFFSET];
|
|
|
|
frag_tag = GET16(RIME_FRAG_PTR, RIME_FRAG_TAG);
|
|
|
|
frag_size = GET16(RIME_FRAG_PTR, RIME_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);
|
|
|
|
rime_hdr_len += SICSLOWPAN_FRAGN_HDR_LEN;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(processed_ip_len > 0) {
|
|
|
|
/* 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 ||
|
2009-03-12 22:58:20 +01:00
|
|
|
!rimeaddr_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
|
|
|
*/
|
|
|
|
if(frag_size > 0){
|
|
|
|
sicslowpan_len = frag_size;
|
|
|
|
reass_tag = frag_tag;
|
|
|
|
timer_set(&reass_timer, SICSLOWPAN_REASS_MAXAGE*CLOCK_SECOND);
|
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);
|
2009-03-12 22:58:20 +01:00
|
|
|
rimeaddr_copy(&frag_sender, packetbuf_addr(PACKETBUF_ADDR_SENDER));
|
2008-10-14 11:42:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(rime_hdr_len == SICSLOWPAN_FRAGN_HDR_LEN) {
|
|
|
|
/* 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
|
|
|
|
if((RIME_HC1_PTR[RIME_HC1_DISPATCH] & 0xe0) == SICSLOWPAN_DISPATCH_IPHC) {
|
|
|
|
PRINTFI("sicslowpan input: IPHC\n");
|
|
|
|
uncompress_hdr_hc06(frag_size);
|
|
|
|
} else
|
|
|
|
#endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
|
|
|
|
switch(RIME_HC1_PTR[RIME_HC1_DISPATCH]) {
|
|
|
|
#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");
|
2008-10-14 11:42:33 +02:00
|
|
|
rime_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
|
|
|
|
|
|
|
|
/* Put uncompressed IP header in sicslowpan_buf. */
|
|
|
|
memcpy(SICSLOWPAN_IP_BUF, rime_ptr + rime_hdr_len, UIP_IPH_LEN);
|
|
|
|
|
|
|
|
/* Update uncomp_hdr_len and rime_hdr_len. */
|
|
|
|
rime_hdr_len += UIP_IPH_LEN;
|
|
|
|
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",
|
2009-04-06 15:11:20 +02:00
|
|
|
RIME_HC1_PTR[RIME_HC1_DISPATCH]);
|
2008-10-14 11:42:33 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
copypayload:
|
|
|
|
#endif /*SICSLOWPAN_CONF_FRAG*/
|
|
|
|
/*
|
2008-10-14 14:26:18 +02:00
|
|
|
* copy "payload" from the rime 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
|
|
|
|
* and rime_hdr_len are non 0, frag_offset is.
|
|
|
|
* If this is a subsequent fragment, this is the contrary.
|
2008-10-14 14:26:18 +02:00
|
|
|
*/
|
2009-03-12 22:58:20 +01:00
|
|
|
rime_payload_len = packetbuf_datalen() - rime_hdr_len;
|
2008-10-14 14:26:18 +02:00
|
|
|
memcpy((void *)SICSLOWPAN_IP_BUF + uncomp_hdr_len + (u16_t)(frag_offset << 3), rime_ptr + rime_hdr_len, rime_payload_len);
|
2008-10-14 11:42:33 +02:00
|
|
|
|
|
|
|
/* update processed_ip_len if fragment, sicslowpan_len otherwise */
|
|
|
|
|
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
if(frag_size > 0){
|
|
|
|
if(processed_ip_len == 0) {
|
|
|
|
processed_ip_len += uncomp_hdr_len;
|
2008-10-14 14:26:18 +02:00
|
|
|
}
|
2008-10-14 11:42:33 +02:00
|
|
|
processed_ip_len += rime_payload_len;
|
|
|
|
} else {
|
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
|
|
|
sicslowpan_len = rime_payload_len + uncomp_hdr_len;
|
|
|
|
#if SICSLOWPAN_CONF_FRAG
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we have a full IP packet in sicslowpan_buf, deliver it to
|
|
|
|
* the IP stack
|
|
|
|
*/
|
|
|
|
if(processed_ip_len == 0 || (processed_ip_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);
|
|
|
|
memcpy((void *)UIP_IP_BUF, (void *)SICSLOWPAN_IP_BUF, sicslowpan_len);
|
|
|
|
uip_len = sicslowpan_len;
|
|
|
|
sicslowpan_len = 0;
|
|
|
|
processed_ip_len = 0;
|
|
|
|
#endif /* SICSLOWPAN_CONF_FRAG */
|
2009-11-02 12:58:56 +01:00
|
|
|
|
2010-02-25 16:50:58 +01:00
|
|
|
#if DEBUG
|
|
|
|
{
|
|
|
|
uint8_t tmp;
|
|
|
|
PRINTF("after decompression: ");
|
|
|
|
for (tmp = 0; tmp < SICSLOWPAN_IP_BUF->len[1] + 40; tmp++) {
|
|
|
|
uint8_t data = ((uint8_t *) (SICSLOWPAN_IP_BUF))[tmp];
|
|
|
|
PRINTF("%02x", data);
|
|
|
|
}
|
|
|
|
PRINTF("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-03-12 14:20:13 +01:00
|
|
|
#if SICSLOWPAN_CONF_NEIGHBOR_INFO
|
|
|
|
neighbor_info_packet_received();
|
|
|
|
#endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */
|
|
|
|
|
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
|
|
|
{
|
|
|
|
/* remember the mac driver */
|
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_mac = &NETSTACK_MAC;
|
2010-02-25 16:50:58 +01: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-03-19 09:15:20 +01:00
|
|
|
#if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
|
2008-10-14 11:42:33 +02:00
|
|
|
addr_contexts[0].used = 1;
|
2010-02-25 16:50:58 +01:00
|
|
|
addr_contexts[0].number = 0;
|
|
|
|
addr_contexts[0].prefix[0] = 0xaa;
|
|
|
|
addr_contexts[0].prefix[1] = 0xaa;
|
2010-03-19 09:15:20 +01:00
|
|
|
#endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
|
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++) {
|
|
|
|
addr_contexts[i].used = 0;
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
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
|
|
|
/** @} */
|