2013-06-22 05:11:53 +02:00
/*
* 6l owpan implementation
*
* Copyright ( C ) 2013 INRIA .
*
* This file subject to the terms and conditions of the GNU Lesser General
* Public License . See the file LICENSE in the top level directory for more
* details .
*
* @ ingroup sixlowpan
* @ {
* @ file sixlowpan . c
2013-08-08 13:39:00 +02:00
* @ brief 6l owpan functions
2013-06-22 05:11:53 +02:00
* @ author Stephan Zeisberg < zeisberg @ mi . fu - berlin . de >
* @ author Martin Lenders < mlenders @ inf . fu - berlin . de >
* @ author Oliver Gesch < oliver . gesch @ googlemail . com >
* @ author Eric Engel < eric . engel @ fu - berlin . de >
* @ }
*/
2012-11-05 22:29:11 +01:00
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <limits.h>
2013-07-27 16:13:53 +02:00
# include <errno.h>
2013-06-14 20:33:28 +02:00
# include "vtimer.h"
# include "timex.h"
# include "thread.h"
# include "mutex.h"
# include "hwtimer.h"
2012-11-05 22:29:11 +01:00
# include "msg.h"
2013-08-08 13:39:00 +02:00
# include "transceiver.h"
2013-08-08 16:22:37 +02:00
# include "sixlowpan/mac.h"
2013-08-14 04:35:58 +02:00
# include "sixlowpan/ndp.h"
2013-08-08 13:39:00 +02:00
2013-08-05 16:10:54 +02:00
# include "lowpan.h"
# include "border.h"
# include "ip.h"
# include "icmp.h"
2013-08-08 13:39:00 +02:00
2013-10-15 13:50:11 +02:00
# include "ieee802154_frame.h"
2013-09-20 15:13:18 +02:00
# include "destiny/in.h"
2013-10-15 13:50:11 +02:00
# include "net_help.h"
2012-11-05 22:29:11 +01:00
2013-10-28 23:35:48 +01:00
# define ENABLE_DEBUG (0)
# if ENABLE_DEBUG
char addr_str [ IPV6_MAX_ADDR_STR_LEN ] ;
# endif
# include "debug.h"
2013-08-14 18:23:53 +02:00
# define IP_PROCESS_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT * 6)
# define NC_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
# define CON_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
# define LOWPAN_TRANSFER_BUF_STACKSIZE (KERNEL_CONF_STACKSIZE_DEFAULT)
2013-08-09 03:13:37 +02:00
2013-08-13 06:41:05 +02:00
# define SIXLOWPAN_MAX_REGISTERED (4)
2013-08-09 03:13:37 +02:00
2013-08-13 06:41:05 +02:00
# define LOWPAN_REAS_BUF_TIMEOUT (15 * 1000 * 1000)
/* TODO: Set back to 3 * 1000 * (1000) */
# define IPV6_LL_ADDR_LEN (8)
2013-08-09 03:13:37 +02:00
2013-08-14 17:36:37 +02:00
# define SIXLOWPAN_FRAG_HDR_MASK (0xf8)
2013-08-09 03:13:37 +02:00
typedef struct lowpan_interval_list_t {
uint8_t start ;
uint8_t end ;
struct lowpan_interval_list_t * next ;
} lowpan_interval_list_t ;
typedef struct lowpan_reas_buf_t {
/* Source Address */
ieee_802154_long_t s_laddr ;
/* Destination Address */
ieee_802154_long_t d_laddr ;
/* Identification Number */
uint16_t ident_no ;
/* Timestamp of last packet fragment */
long timestamp ;
/* Size of reassembled packet with possible IPHC header */
uint16_t packet_size ;
/* Additive size of currently already received fragments */
uint16_t current_packet_size ;
/* Pointer to allocated memory for reassembled packet + 6LoWPAN Dispatch Byte */
uint8_t * packet ;
/* Pointer to list of intervals of received packet fragments (if any) */
lowpan_interval_list_t * interval_list_head ;
/* Pointer to next reassembly buffer (if any) */
struct lowpan_reas_buf_t * next ;
} lowpan_reas_buf_t ;
2013-08-13 06:41:05 +02:00
extern mutex_t lowpan_context_mutex ;
2012-11-05 22:29:11 +01:00
uint16_t tag ;
uint8_t header_size = 0 ;
uint8_t max_frame = 0 ;
uint8_t max_frag_initial = 0 ;
uint8_t position ;
uint8_t max_frag ;
2013-08-09 03:13:37 +02:00
static uint16_t packet_length ;
static sixlowpan_lowpan_iphc_status_t iphc_status = LOWPAN_IPHC_ENABLE ;
2013-07-24 23:22:11 +02:00
static ipv6_hdr_t * ipv6_buf ;
2013-08-09 03:13:37 +02:00
static lowpan_reas_buf_t * head = NULL ;
static lowpan_reas_buf_t * packet_fifo = NULL ;
2012-11-05 22:29:11 +01:00
/* length of compressed packet */
uint16_t comp_len ;
uint8_t frag_size ;
uint8_t reas_buf [ 512 ] ;
uint8_t comp_buf [ 512 ] ;
uint8_t byte_offset ;
uint8_t first_frag = 0 ;
mutex_t fifo_mutex ;
unsigned int ip_process_pid ;
unsigned int nd_nbr_cache_rem_pid = 0 ;
unsigned int contexts_rem_pid = 0 ;
unsigned int transfer_pid = 0 ;
iface_t iface ;
ipv6_addr_t lladdr ;
ieee_802154_long_t laddr ;
mutex_t lowpan_context_mutex ;
2013-07-27 16:13:53 +02:00
/* registered upper layer threads */
int sixlowpan_reg [ SIXLOWPAN_MAX_REGISTERED ] ;
2012-11-05 22:29:11 +01:00
char ip_process_buf [ IP_PROCESS_STACKSIZE ] ;
char nc_buf [ NC_STACKSIZE ] ;
char con_buf [ CON_STACKSIZE ] ;
char lowpan_transfer_buf [ LOWPAN_TRANSFER_BUF_STACKSIZE ] ;
2013-08-14 04:35:58 +02:00
lowpan_context_t contexts [ NDP_6LOWPAN_CONTEXT_MAX ] ;
2012-11-05 22:29:11 +01:00
uint8_t context_len = 0 ;
uint16_t local_address = 0 ;
2013-10-28 23:35:48 +01:00
void lowpan_init ( transceiver_type_t trans , uint8_t r_addr ,
const ipv6_addr_t * prefix , int as_border ) ;
2012-11-05 22:29:11 +01:00
void lowpan_context_auto_remove ( void ) ;
2013-08-09 03:13:37 +02:00
void lowpan_iphc_encoding ( ieee_802154_long_t * dest ,
ipv6_hdr_t * ipv6_buf_extra , uint8_t * ptr ) ;
void lowpan_iphc_decoding ( uint8_t * data , uint8_t length ,
ieee_802154_long_t * s_laddr ,
ieee_802154_long_t * d_laddr ) ;
void add_fifo_packet ( lowpan_reas_buf_t * current_packet ) ;
lowpan_reas_buf_t * collect_garbage_fifo ( lowpan_reas_buf_t * current_buf ) ;
lowpan_reas_buf_t * collect_garbage ( lowpan_reas_buf_t * current_buf ) ;
void init_reas_bufs ( lowpan_reas_buf_t * buf ) ;
void check_timeout ( void ) ;
lowpan_context_t * lowpan_context_lookup ( ipv6_addr_t * addr ) ;
void lowpan_ipv6_set_dispatch ( uint8_t * data ) ;
2012-11-05 22:29:11 +01:00
/* deliver packet to mac*/
2013-08-13 06:41:05 +02:00
void sixlowpan_lowpan_sendto ( const ieee_802154_long_t * dest ,
2013-08-09 03:13:37 +02:00
uint8_t * data , uint16_t data_len )
2013-06-22 05:11:53 +02:00
{
2012-11-05 22:29:11 +01:00
uint8_t mcast = 0 ;
2013-06-22 05:11:53 +02:00
ipv6_buf = ( ipv6_hdr_t * ) data ;
2013-08-09 03:13:37 +02:00
packet_length = data_len ;
2012-11-05 22:29:11 +01:00
2013-08-09 03:13:37 +02:00
memcpy ( & laddr . uint8 [ 0 ] , & dest - > uint8 [ 0 ] , 8 ) ;
2012-11-05 22:29:11 +01:00
2013-08-13 06:41:05 +02:00
if ( ipv6_addr_is_multicast ( & ipv6_buf - > destaddr ) ) {
2012-11-05 22:29:11 +01:00
/* send broadcast */
mcast = 1 ;
2013-06-22 05:11:53 +02:00
}
2013-08-09 03:13:37 +02:00
2013-07-25 16:12:09 +02:00
if ( iphc_status = = LOWPAN_IPHC_ENABLE ) {
lowpan_iphc_encoding ( & laddr , ipv6_buf , data ) ;
data = & comp_buf [ 0 ] ;
packet_length = comp_len ;
2013-08-09 03:13:37 +02:00
}
else {
2013-10-24 01:11:01 +02:00
ipv6_buf - > length = HTONS ( ipv6_buf - > length ) ;
2013-07-25 16:12:09 +02:00
lowpan_ipv6_set_dispatch ( data ) ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* check if packet needs to be fragmented */
2013-06-24 22:37:35 +02:00
if ( packet_length + header_size > PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN ) {
2012-11-05 22:29:11 +01:00
uint8_t fragbuf [ packet_length + header_size ] ;
uint8_t remaining ;
uint8_t i = 2 ;
/* first fragment */
max_frame = PAYLOAD_SIZE - IEEE_802154_MAX_HDR_LEN ;
max_frag_initial = ( ( max_frame - 4 - header_size ) / 8 ) * 8 ;
2013-06-22 05:11:53 +02:00
memcpy ( fragbuf + 4 , data , max_frag_initial ) ;
2013-08-14 17:35:30 +02:00
fragbuf [ 0 ] = ( ( SIXLOWPAN_FRAG1_DISPATCH < < 8 ) | packet_length ) > > 8 ;
fragbuf [ 1 ] = ( SIXLOWPAN_FRAG1_DISPATCH < < 8 ) | packet_length ;
fragbuf [ 2 ] = tag > > 8 ;
fragbuf [ 3 ] = tag ;
2012-11-05 22:29:11 +01:00
2013-08-08 16:22:37 +02:00
sixlowpan_mac_send_ieee802154_frame ( & laddr ,
( uint8_t * ) & fragbuf ,
max_frag_initial + header_size + 4 ,
mcast ) ;
2012-11-05 22:29:11 +01:00
/* subsequent fragments */
position = max_frag_initial ;
max_frag = ( ( max_frame - 5 ) / 8 ) * 8 ;
2013-06-22 05:11:53 +02:00
data + = position ;
2012-11-05 22:29:11 +01:00
2013-06-24 22:37:35 +02:00
while ( packet_length - position > max_frame - 5 ) {
2013-06-22 05:11:53 +02:00
memset ( & fragbuf , 0 , packet_length + header_size ) ;
2012-11-05 22:29:11 +01:00
memcpy ( fragbuf + 5 , data , max_frag ) ;
2013-06-22 05:11:53 +02:00
2013-08-14 17:35:30 +02:00
fragbuf [ 0 ] = ( ( SIXLOWPAN_FRAGN_DISPATCH < < 8 ) | packet_length ) > > 8 ;
fragbuf [ 1 ] = ( SIXLOWPAN_FRAGN_DISPATCH < < 8 ) | packet_length ;
fragbuf [ 2 ] = tag > > 8 ;
fragbuf [ 3 ] = tag ;
2012-11-05 22:29:11 +01:00
fragbuf [ 4 ] = position / 8 ;
2013-06-22 05:11:53 +02:00
2013-08-08 16:22:37 +02:00
sixlowpan_mac_send_ieee802154_frame ( & laddr ,
( uint8_t * ) & fragbuf ,
max_frag + 5 , mcast ) ;
2012-11-05 22:29:11 +01:00
data + = max_frag ;
position + = max_frag ;
2013-06-22 05:11:53 +02:00
i + + ;
2012-11-05 22:29:11 +01:00
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
remaining = packet_length - position ;
2013-06-22 05:11:53 +02:00
memset ( & fragbuf , 0 , packet_length + header_size ) ;
memcpy ( fragbuf + 5 , data , remaining ) ;
2013-08-14 17:35:30 +02:00
fragbuf [ 0 ] = ( ( SIXLOWPAN_FRAGN_DISPATCH < < 8 ) | packet_length ) > > 8 ;
fragbuf [ 1 ] = ( SIXLOWPAN_FRAGN_DISPATCH < < 8 ) | packet_length ;
fragbuf [ 2 ] = tag > > 8 ;
fragbuf [ 3 ] = tag ;
2012-11-05 22:29:11 +01:00
fragbuf [ 4 ] = position / 8 ;
2013-08-08 16:22:37 +02:00
sixlowpan_mac_send_ieee802154_frame ( & laddr ,
( uint8_t * ) & fragbuf ,
remaining + 5 , mcast ) ;
2013-06-22 05:11:53 +02:00
}
else {
2013-08-08 16:22:37 +02:00
sixlowpan_mac_send_ieee802154_frame ( & laddr , data ,
packet_length , mcast ) ;
2013-06-22 05:11:53 +02:00
}
2012-11-05 22:29:11 +01:00
tag + + ;
}
2013-08-09 03:13:37 +02:00
void sixlowpan_lowpan_set_iphc_status (
sixlowpan_lowpan_iphc_status_t status )
2013-07-25 16:12:09 +02:00
{
iphc_status = status ;
}
2013-08-09 03:13:37 +02:00
# if ENABLE_DEBUG
void print_long_local_addr ( ieee_802154_long_t * saddr )
2013-06-22 05:11:53 +02:00
{
printf ( " %02x%02x:%02x%02x:%02x%02x:%02x%02x \n " ,
( ( uint8_t * ) saddr ) [ 0 ] , ( ( uint8_t * ) saddr ) [ 1 ] , ( ( uint8_t * ) saddr ) [ 2 ] ,
( ( uint8_t * ) saddr ) [ 3 ] , ( ( uint8_t * ) saddr ) [ 4 ] , ( ( uint8_t * ) saddr ) [ 5 ] ,
( ( uint8_t * ) saddr ) [ 6 ] , ( ( uint8_t * ) saddr ) [ 7 ] ) ;
}
2012-11-05 22:29:11 +01:00
2013-08-09 03:13:37 +02:00
void sixlowpan_lowpan_print_reassembly_buffers ( void )
2013-06-22 05:11:53 +02:00
{
lowpan_reas_buf_t * temp_buffer ;
lowpan_interval_list_t * temp_interval ;
temp_buffer = head ;
printf ( " \n \n --- Reassembly Buffers --- \n " ) ;
2013-06-24 22:37:35 +02:00
while ( temp_buffer ! = NULL ) {
2013-08-09 03:13:37 +02:00
print_long_local_addr ( & temp_buffer - > s_laddr ) ;
2013-06-22 05:11:53 +02:00
printf ( " Ident.: %i, Packet Size: %i/%i, Timestamp: %li \n " ,
temp_buffer - > ident_no , temp_buffer - > current_packet_size ,
temp_buffer - > packet_size , temp_buffer - > timestamp ) ;
temp_interval = temp_buffer - > interval_list_head ;
2013-06-24 22:37:35 +02:00
while ( temp_interval ! = NULL ) {
2013-06-22 05:11:53 +02:00
printf ( " \t %i - %i \n " , temp_interval - > start , temp_interval - > end ) ;
temp_interval = temp_interval - > next ;
}
temp_buffer = temp_buffer - > next ;
}
}
2012-11-05 22:29:11 +01:00
2013-08-09 03:13:37 +02:00
void sixlowpan_lowpan_print_fifo_buffers ( void )
2013-06-22 05:11:53 +02:00
{
lowpan_reas_buf_t * temp_buffer ;
lowpan_interval_list_t * temp_interval ;
temp_buffer = packet_fifo ;
printf ( " \n \n --- Reassembly Buffers --- \n " ) ;
2013-06-24 22:37:35 +02:00
while ( temp_buffer ! = NULL ) {
2013-08-09 03:13:37 +02:00
print_long_local_addr ( & temp_buffer - > s_laddr ) ;
2013-06-22 05:11:53 +02:00
printf ( " Ident.: %i, Packet Size: %i/%i, Timestamp: %li \n " ,
2013-08-08 13:39:00 +02:00
temp_buffer - > ident_no , temp_buffer - > current_packet_size ,
2013-06-22 05:11:53 +02:00
temp_buffer - > packet_size , temp_buffer - > timestamp ) ;
temp_interval = temp_buffer - > interval_list_head ;
2013-06-24 22:37:35 +02:00
while ( temp_interval ! = NULL ) {
2013-06-22 05:11:53 +02:00
printf ( " \t %i - %i \n " , temp_interval - > start , temp_interval - > end ) ;
temp_interval = temp_interval - > next ;
}
temp_buffer = temp_buffer - > next ;
}
}
2013-08-09 03:13:37 +02:00
# endif
2012-11-05 22:29:11 +01:00
void lowpan_transfer ( void )
2013-06-22 05:11:53 +02:00
{
msg_t m_recv , m_send ;
ipv6_hdr_t * ipv6_buf ;
lowpan_reas_buf_t * current_buf ;
uint8_t gotosleep ;
2013-06-24 22:37:35 +02:00
while ( 1 ) {
2013-06-22 05:11:53 +02:00
gotosleep = 1 ;
mutex_lock ( & fifo_mutex ) ;
current_buf = packet_fifo ;
2013-06-24 22:37:35 +02:00
if ( current_buf ! = NULL ) {
2013-08-04 04:06:31 +02:00
mutex_unlock ( & fifo_mutex ) ;
2013-06-22 05:11:53 +02:00
2013-08-09 03:13:37 +02:00
if ( ( current_buf - > packet ) [ 0 ] = = SIXLOWPAN_IPV6_DISPATCH ) {
2013-08-13 06:41:05 +02:00
ipv6_buf = ipv6_get_buf ( ) ;
2013-06-22 05:11:53 +02:00
memcpy ( ipv6_buf , ( current_buf - > packet ) + 1 , current_buf - > packet_size - 1 ) ;
m_send . content . ptr = ( char * ) ipv6_buf ;
packet_length = current_buf - > packet_size - 1 ;
msg_send_receive ( & m_send , & m_recv , ip_process_pid ) ;
}
2013-08-09 03:13:37 +02:00
else if ( ( ( current_buf - > packet ) [ 0 ] & 0xe0 ) = = SIXLOWPAN_IPHC1_DISPATCH ) {
2013-06-22 05:11:53 +02:00
lowpan_iphc_decoding ( current_buf - > packet ,
current_buf - > packet_size ,
2013-06-24 14:10:53 +02:00
& ( current_buf - > s_laddr ) ,
& ( current_buf - > d_laddr ) ) ;
2013-06-22 05:11:53 +02:00
2013-08-13 06:41:05 +02:00
ipv6_buf = ipv6_get_buf ( ) ;
2013-06-22 05:11:53 +02:00
m_send . content . ptr = ( char * ) ipv6_buf ;
msg_send_receive ( & m_send , & m_recv , ip_process_pid ) ;
}
else {
// printf("ERROR: packet with unknown dispatch received\n");
}
collect_garbage_fifo ( current_buf ) ;
gotosleep = 0 ;
}
2013-06-24 22:37:35 +02:00
if ( gotosleep = = 1 ) {
2013-08-04 04:06:31 +02:00
mutex_unlock ( & fifo_mutex ) ;
2013-06-22 05:11:53 +02:00
thread_sleep ( ) ;
}
}
}
uint8_t ll_get_addr_match ( ieee_802154_long_t * src , ieee_802154_long_t * dst )
{
2012-11-05 22:29:11 +01:00
uint8_t val = 0 , xor ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
for ( int i = 0 ; i < 8 ; i + + ) {
2012-11-05 22:29:11 +01:00
/* if bytes are equal add 8 */
2013-06-24 22:37:35 +02:00
if ( src - > uint8 [ i ] = = dst - > uint8 [ i ] ) {
2012-11-05 22:29:11 +01:00
val + = 8 ;
2013-06-22 05:11:53 +02:00
}
else {
2012-11-05 22:29:11 +01:00
xor = src - > uint8 [ i ] ^ dst - > uint8 [ i ] ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* while bits from byte equal add 1 */
2013-06-24 22:37:35 +02:00
for ( int j = 0 ; j < 8 ; j + + ) {
if ( ( xor & 0x80 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
val + + ;
xor = xor < < 1 ;
2013-06-22 05:11:53 +02:00
}
else {
2012-11-05 22:29:11 +01:00
break ;
}
}
}
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
return val ;
}
2013-06-22 05:11:53 +02:00
lowpan_reas_buf_t * new_packet_buffer ( uint16_t datagram_size ,
uint16_t datagram_tag ,
ieee_802154_long_t * s_laddr ,
ieee_802154_long_t * d_laddr ,
lowpan_reas_buf_t * current_buf ,
lowpan_reas_buf_t * temp_buf )
{
lowpan_reas_buf_t * new_buf = NULL ;
/* Allocate new memory for a new packet to be reassembled */
new_buf = malloc ( sizeof ( lowpan_reas_buf_t ) ) ;
2013-06-24 22:37:35 +02:00
if ( new_buf ! = NULL ) {
2013-06-22 05:11:53 +02:00
init_reas_bufs ( new_buf ) ;
new_buf - > packet = malloc ( datagram_size ) ;
2013-06-24 22:37:35 +02:00
if ( new_buf - > packet ! = NULL ) {
2013-08-13 06:41:05 +02:00
memcpy ( & new_buf - > s_laddr , s_laddr , IPV6_LL_ADDR_LEN ) ;
memcpy ( & new_buf - > d_laddr , d_laddr , IPV6_LL_ADDR_LEN ) ;
2013-06-22 05:11:53 +02:00
new_buf - > ident_no = datagram_tag ;
new_buf - > packet_size = datagram_size ;
timex_t now ;
vtimer_now ( & now ) ;
new_buf - > timestamp = now . microseconds ;
2013-06-24 22:37:35 +02:00
if ( ( current_buf = = NULL ) & & ( temp_buf = = NULL ) ) {
2013-06-22 05:11:53 +02:00
head = new_buf ;
}
else {
temp_buf - > next = new_buf ;
}
return new_buf ;
}
else {
return NULL ;
}
}
else {
return NULL ;
}
}
lowpan_reas_buf_t * get_packet_frag_buf ( uint16_t datagram_size ,
uint16_t datagram_tag ,
ieee_802154_long_t * s_laddr ,
ieee_802154_long_t * d_laddr )
{
lowpan_reas_buf_t * current_buf = NULL , * temp_buf = NULL ;
current_buf = head ;
2013-06-24 22:37:35 +02:00
while ( current_buf ! = NULL ) {
if ( ( ( ll_get_addr_match ( & current_buf - > s_laddr , s_laddr ) ) = = 64 ) & &
2013-08-08 13:39:00 +02:00
( ( ll_get_addr_match ( & current_buf - > d_laddr , d_laddr ) ) = = 64 ) & &
( current_buf - > packet_size = = datagram_size ) & &
( current_buf - > ident_no = = datagram_tag ) & &
current_buf - > interval_list_head ! = NULL ) {
2013-06-22 05:11:53 +02:00
/* Found buffer for current packet fragment */
timex_t now ;
vtimer_now ( & now ) ;
current_buf - > timestamp = now . microseconds ;
return current_buf ;
}
temp_buf = current_buf ;
current_buf = current_buf - > next ;
}
return new_packet_buffer ( datagram_size , datagram_tag , s_laddr , d_laddr ,
current_buf , temp_buf ) ;
}
2012-11-05 22:29:11 +01:00
2013-08-09 03:13:37 +02:00
uint8_t is_in_interval ( uint8_t start1 , uint8_t end1 , uint8_t start2 , uint8_t end2 )
2013-06-22 05:11:53 +02:00
{
/* 1: Interval 1 and 2 are the same or overlapping */
/* 0: Interval 1 and 2 are not overlapping or the same */
2013-06-24 22:37:35 +02:00
if ( ( ( start1 < start2 ) & & ( start2 < = end1 ) ) | |
2013-08-08 13:39:00 +02:00
( ( start2 < start1 ) & & ( start1 < = end2 ) ) | |
( ( start1 = = start2 ) & & ( end1 = = end2 ) ) ) {
2013-06-22 05:11:53 +02:00
return 1 ;
}
else {
return 0 ;
}
}
uint8_t handle_packet_frag_interval ( lowpan_reas_buf_t * current_buf ,
uint8_t datagram_offset , uint8_t frag_size )
{
/* 0: Error, discard fragment */
/* 1: Finished correctly */
lowpan_interval_list_t * temp_interval = NULL , * current_interval = NULL , * new_interval = NULL ;
current_interval = current_buf - > interval_list_head ;
2013-06-24 22:37:35 +02:00
while ( current_interval ! = NULL ) {
2013-08-09 03:13:37 +02:00
if ( is_in_interval ( current_interval - > start , current_interval - > end , datagram_offset , datagram_offset + frag_size ) = = 1 ) {
2013-06-22 05:11:53 +02:00
/* Interval is overlapping or the same as one of a previous fragment, discard fragment */
return 0 ;
}
temp_interval = current_interval ;
current_interval = current_interval - > next ;
}
new_interval = malloc ( sizeof ( lowpan_interval_list_t ) ) ;
2013-06-24 22:37:35 +02:00
if ( new_interval ! = NULL ) {
2013-06-22 05:11:53 +02:00
new_interval - > start = datagram_offset ;
new_interval - > end = datagram_offset + frag_size - 1 ;
new_interval - > next = NULL ;
2013-06-24 22:37:35 +02:00
if ( ( current_interval = = NULL ) & & ( temp_interval = = NULL ) ) {
2013-06-22 05:11:53 +02:00
current_buf - > interval_list_head = new_interval ;
}
else {
temp_interval - > next = new_interval ;
}
return 1 ;
}
return 0 ;
}
2012-11-05 22:29:11 +01:00
lowpan_reas_buf_t * collect_garbage_fifo ( lowpan_reas_buf_t * current_buf )
2013-06-22 05:11:53 +02:00
{
lowpan_interval_list_t * temp_list , * current_list ;
lowpan_reas_buf_t * temp_buf , * my_buf , * return_buf ;
mutex_lock ( & fifo_mutex ) ;
temp_buf = packet_fifo ;
my_buf = temp_buf ;
2013-06-24 22:37:35 +02:00
if ( packet_fifo = = current_buf ) {
2013-06-22 05:11:53 +02:00
packet_fifo = current_buf - > next ;
return_buf = packet_fifo ;
}
else {
2013-06-24 22:37:35 +02:00
while ( temp_buf ! = current_buf ) {
2013-06-22 05:11:53 +02:00
my_buf = temp_buf ;
temp_buf = temp_buf - > next ;
}
my_buf - > next = current_buf - > next ;
return_buf = my_buf - > next ;
}
2013-08-04 04:06:31 +02:00
mutex_unlock ( & fifo_mutex ) ;
2013-06-22 05:11:53 +02:00
current_list = current_buf - > interval_list_head ;
temp_list = current_list ;
2013-06-24 22:37:35 +02:00
while ( current_list ! = NULL ) {
2013-06-22 05:11:53 +02:00
temp_list = current_list - > next ;
free ( current_list ) ;
current_list = temp_list ;
}
free ( current_buf - > packet ) ;
free ( current_buf ) ;
return return_buf ;
}
2012-11-05 22:29:11 +01:00
lowpan_reas_buf_t * collect_garbage ( lowpan_reas_buf_t * current_buf )
2013-06-22 05:11:53 +02:00
{
lowpan_interval_list_t * temp_list , * current_list ;
lowpan_reas_buf_t * temp_buf , * my_buf , * return_buf ;
temp_buf = head ;
my_buf = temp_buf ;
2013-06-24 22:37:35 +02:00
if ( head = = current_buf ) {
2013-06-22 05:11:53 +02:00
head = current_buf - > next ;
return_buf = head ;
}
else {
2013-06-24 22:37:35 +02:00
while ( temp_buf ! = current_buf ) {
2013-06-22 05:11:53 +02:00
my_buf = temp_buf ;
temp_buf = temp_buf - > next ;
}
my_buf - > next = current_buf - > next ;
return_buf = my_buf - > next ;
}
current_list = current_buf - > interval_list_head ;
temp_list = current_list ;
2013-06-24 22:37:35 +02:00
while ( current_list ! = NULL ) {
2013-06-22 05:11:53 +02:00
temp_list = current_list - > next ;
free ( current_list ) ;
current_list = temp_list ;
}
free ( current_buf - > packet ) ;
free ( current_buf ) ;
return return_buf ;
}
2013-08-08 13:39:00 +02:00
void handle_packet_fragment ( uint8_t * data , uint8_t datagram_offset ,
2013-06-22 05:11:53 +02:00
uint16_t datagram_size , uint16_t datagram_tag ,
ieee_802154_long_t * s_laddr ,
ieee_802154_long_t * d_laddr , uint8_t hdr_length ,
uint8_t frag_size )
{
lowpan_reas_buf_t * current_buf ;
/* Is there already a reassembly buffer for this packet fragment? */
current_buf = get_packet_frag_buf ( datagram_size , datagram_tag , s_laddr , d_laddr ) ;
2013-06-24 22:37:35 +02:00
if ( ( current_buf ! = NULL ) & & ( handle_packet_frag_interval ( current_buf ,
2013-08-08 13:39:00 +02:00
datagram_offset ,
frag_size ) = = 1 ) ) {
2013-06-22 05:11:53 +02:00
/* Copy fragment bytes into corresponding packet space area */
memcpy ( current_buf - > packet + datagram_offset , data + hdr_length , frag_size ) ;
current_buf - > current_packet_size + = frag_size ;
2013-06-24 22:37:35 +02:00
if ( current_buf - > current_packet_size = = current_buf - > packet_size ) {
2013-06-22 05:11:53 +02:00
add_fifo_packet ( current_buf ) ;
2013-06-24 22:37:35 +02:00
if ( thread_getstatus ( transfer_pid ) = = STATUS_SLEEPING ) {
2013-06-22 05:11:53 +02:00
thread_wakeup ( transfer_pid ) ;
}
}
}
else {
/* No memory left or duplicate */
2013-06-24 22:37:35 +02:00
if ( current_buf = = NULL ) {
2013-06-22 05:11:53 +02:00
printf ( " ERROR: no memory left! \n " ) ;
}
else {
printf ( " ERROR: duplicate fragment! \n " ) ;
}
}
}
2012-11-05 22:29:11 +01:00
void check_timeout ( void )
2013-06-22 05:11:53 +02:00
{
lowpan_reas_buf_t * temp_buf , * smallest_time = NULL ;
long cur_time ;
int count = 0 ;
timex_t now ;
vtimer_now ( & now ) ;
cur_time = now . microseconds ;
temp_buf = head ;
2013-06-24 22:37:35 +02:00
while ( temp_buf ! = NULL ) {
if ( ( cur_time - temp_buf - > timestamp ) > = LOWPAN_REAS_BUF_TIMEOUT ) {
printf ( " TIMEOUT!cur_time: %li, temp_buf: %li \n " , cur_time ,
2013-06-22 05:11:53 +02:00
temp_buf - > timestamp ) ;
temp_buf = collect_garbage ( temp_buf ) ;
}
else {
2013-06-24 22:37:35 +02:00
if ( smallest_time = = NULL ) {
2013-06-22 05:11:53 +02:00
smallest_time = temp_buf ;
}
2013-06-24 22:37:35 +02:00
else if ( temp_buf - > timestamp < smallest_time - > timestamp ) {
2013-06-22 05:11:53 +02:00
smallest_time = temp_buf ;
}
temp_buf = temp_buf - > next ;
count + + ;
}
}
2013-06-24 22:37:35 +02:00
if ( ( count > 10 ) & & ( smallest_time ! = NULL ) ) {
2013-06-22 05:11:53 +02:00
collect_garbage ( smallest_time ) ;
}
}
2012-11-05 22:29:11 +01:00
void add_fifo_packet ( lowpan_reas_buf_t * current_packet )
2013-06-22 05:11:53 +02:00
{
lowpan_reas_buf_t * temp_buf , * my_buf ;
2013-06-24 22:37:35 +02:00
if ( head = = current_packet ) {
2013-06-22 05:11:53 +02:00
head = current_packet - > next ;
}
else {
temp_buf = head ;
2013-06-24 22:37:35 +02:00
while ( temp_buf ! = current_packet ) {
2013-06-22 05:11:53 +02:00
my_buf = temp_buf ;
temp_buf = temp_buf - > next ;
}
my_buf - > next = current_packet - > next ;
}
mutex_lock ( & fifo_mutex ) ;
2013-06-24 22:37:35 +02:00
if ( packet_fifo = = NULL ) {
2013-06-22 05:11:53 +02:00
packet_fifo = current_packet ;
}
else {
temp_buf = packet_fifo ;
2013-06-24 22:37:35 +02:00
while ( temp_buf ! = NULL ) {
2013-06-22 05:11:53 +02:00
my_buf = temp_buf ;
temp_buf = temp_buf - > next ;
}
my_buf - > next = current_packet ;
}
2013-08-04 04:06:31 +02:00
mutex_unlock ( & fifo_mutex ) ;
2013-06-22 05:11:53 +02:00
current_packet - > next = NULL ;
}
2012-11-05 22:29:11 +01:00
2013-07-27 16:13:53 +02:00
/* Register an upper layer thread */
2013-08-09 03:13:37 +02:00
uint8_t sixlowpan_lowpan_register ( int pid )
2013-07-27 16:13:53 +02:00
{
uint8_t i ;
2013-08-09 03:13:37 +02:00
for ( i = 0 ; ( ( sixlowpan_reg [ i ] ! = pid ) & & ( i < SIXLOWPAN_MAX_REGISTERED ) & &
( sixlowpan_reg [ i ] ! = 0 ) ) ; i + + ) {
;
}
2013-07-27 16:13:53 +02:00
if ( i > = SIXLOWPAN_MAX_REGISTERED ) {
return ENOMEM ;
}
else {
sixlowpan_reg [ i ] = pid ;
return 1 ;
}
}
2012-11-05 22:29:11 +01:00
void lowpan_read ( uint8_t * data , uint8_t length , ieee_802154_long_t * s_laddr ,
2013-06-22 05:11:53 +02:00
ieee_802154_long_t * d_laddr )
{
2012-11-05 22:29:11 +01:00
/* check if packet is fragmented */
uint8_t hdr_length = 0 ;
2013-06-22 05:11:53 +02:00
uint8_t datagram_offset = 0 ;
2012-11-05 22:29:11 +01:00
uint16_t datagram_size = 0 ;
uint16_t datagram_tag = 0 ;
2013-07-27 16:13:53 +02:00
short i ;
2013-08-09 03:13:37 +02:00
sixlowpan_lowpan_frame_t current_frame ;
2012-11-05 22:29:11 +01:00
check_timeout ( ) ;
2013-07-27 16:13:53 +02:00
for ( i = 0 ; i < SIXLOWPAN_MAX_REGISTERED ; i + + ) {
if ( sixlowpan_reg [ i ] ) {
msg_t m_send ;
2013-08-09 03:13:37 +02:00
current_frame . length = length ;
current_frame . data = data ;
m_send . content . ptr = ( char * ) & current_frame ;
2013-07-27 16:13:53 +02:00
msg_send ( & m_send , sixlowpan_reg [ i ] , 1 ) ;
}
}
2013-08-09 03:13:37 +02:00
2012-11-05 22:29:11 +01:00
/* Fragmented Packet */
2013-08-15 09:48:53 +02:00
if ( ( ( data [ 0 ] & SIXLOWPAN_FRAG_HDR_MASK ) = = SIXLOWPAN_FRAG1_DISPATCH ) | |
2013-08-14 17:36:37 +02:00
( ( data [ 0 ] & SIXLOWPAN_FRAG_HDR_MASK ) = = SIXLOWPAN_FRAGN_DISPATCH ) ) {
2013-06-22 05:11:53 +02:00
/* get 11-bit from first 2 byte*/
datagram_size = ( ( ( uint16_t ) ( data [ 0 ] < < 8 ) ) | data [ 1 ] ) & 0x07ff ;
/* get 16-bit datagram tag */
datagram_tag = ( ( ( uint16_t ) ( data [ 2 ] < < 8 ) ) | data [ 3 ] ) ;
2013-08-14 17:36:37 +02:00
switch ( data [ 0 ] & SIXLOWPAN_FRAG_HDR_MASK ) {
2013-06-22 05:11:53 +02:00
/* First Fragment */
2013-08-09 03:13:37 +02:00
case ( SIXLOWPAN_FRAG1_DISPATCH ) : {
2013-06-22 05:11:53 +02:00
datagram_offset = 0 ;
hdr_length + = 4 ;
break ;
}
/* Subsequent Fragment */
2013-08-09 03:13:37 +02:00
case ( SIXLOWPAN_FRAGN_DISPATCH ) : {
2013-06-22 05:11:53 +02:00
datagram_offset = data [ 4 ] ;
hdr_length + = 5 ;
break ;
}
}
frag_size = length - hdr_length ;
byte_offset = datagram_offset * 8 ;
2013-06-24 22:37:35 +02:00
if ( ( frag_size % 8 ) ! = 0 ) {
if ( ( byte_offset + frag_size ) ! = datagram_size ) {
2013-06-22 05:11:53 +02:00
printf ( " ERROR: received invalid fragment \n " ) ;
return ;
}
}
handle_packet_fragment ( data , byte_offset , datagram_size , datagram_tag ,
s_laddr , d_laddr , hdr_length , frag_size ) ;
}
2012-11-05 22:29:11 +01:00
/* Regular Packet */
2013-06-22 05:11:53 +02:00
else {
lowpan_reas_buf_t * current_buf = get_packet_frag_buf ( length , 0 , s_laddr ,
2013-08-08 13:39:00 +02:00
d_laddr ) ;
2013-09-24 07:35:50 +02:00
if ( current_buf & & current_buf - > packet ) {
2013-09-23 12:32:37 +02:00
/* Copy packet bytes into corresponding packet space area */
memcpy ( current_buf - > packet , data , length ) ;
current_buf - > current_packet_size + = length ;
add_fifo_packet ( current_buf ) ;
2013-09-24 07:35:50 +02:00
}
else {
DEBUG ( " ERROR: no memory left in packet buffer! \n " ) ;
2013-09-23 12:32:37 +02:00
}
2013-06-24 22:37:35 +02:00
if ( thread_getstatus ( transfer_pid ) = = STATUS_SLEEPING ) {
2013-06-22 05:11:53 +02:00
thread_wakeup ( transfer_pid ) ;
}
}
}
void lowpan_ipv6_set_dispatch ( uint8_t * data )
{
2012-11-05 22:29:11 +01:00
memmove ( data + 1 , data , packet_length ) ;
2013-08-09 03:13:37 +02:00
data [ 0 ] = SIXLOWPAN_IPV6_DISPATCH ;
2012-11-05 22:29:11 +01:00
packet_length + + ;
}
/* draft-ietf-6lowpan-hc-13#section-3.1 */
2013-06-22 05:11:53 +02:00
void lowpan_iphc_encoding ( ieee_802154_long_t * dest , ipv6_hdr_t * ipv6_buf_extra ,
uint8_t * ptr )
{
ipv6_buf = ipv6_buf_extra ;
2012-11-05 22:29:11 +01:00
uint16_t payload_length = ipv6_buf - > length ;
uint8_t lowpan_iphc [ 2 ] ;
uint8_t * ipv6_hdr_fields = & comp_buf [ 2 ] ;
lowpan_context_t * con = NULL ;
uint16_t hdr_pos = 0 ;
uint8_t tc ;
memset ( & lowpan_iphc , 0 , 2 ) ;
/* set iphc dispatch */
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 0 ] = SIXLOWPAN_IPHC1_DISPATCH ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* TF: Traffic Class, Flow Label:
2013-06-22 05:11:53 +02:00
* first we need to change DSCP and ECN because in 6l owpan - nd - 13 these
2012-11-05 22:29:11 +01:00
* fields are reverse , the original order is DSCP / ECN ( rfc 3168 ) */
2013-06-22 05:11:53 +02:00
tc = ( ipv6_buf - > version_trafficclass < < 4 ) |
( ipv6_buf - > trafficclass_flowlabel > > 4 ) ;
2012-11-05 22:29:11 +01:00
tc = ( tc > > 2 ) | ( tc < < 6 ) ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
if ( ( ipv6_buf - > flowlabel = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ipv6_buf - > trafficclass_flowlabel & 0x0f ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* flowlabel is elided */
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 0 ] | = SIXLOWPAN_IPHC1_FL_C ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
if ( ( ( ipv6_buf - > version_trafficclass & 0x0f ) = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ( ipv6_buf - > trafficclass_flowlabel & 0xf0 ) = = 0 ) ) {
2012-11-05 22:29:11 +01:00
/* traffic class is elided */
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 0 ] | = SIXLOWPAN_IPHC1_TC_C ;
2013-06-22 05:11:53 +02:00
}
else {
2012-11-05 22:29:11 +01:00
/* ECN + DSCP (1 byte), Flow Label is elided */
ipv6_hdr_fields [ hdr_pos ] = tc ;
hdr_pos + + ;
2013-06-22 05:11:53 +02:00
}
}
else {
2012-11-05 22:29:11 +01:00
/* flowlabel not compressible */
2013-06-24 22:37:35 +02:00
if ( ( ( ipv6_buf - > version_trafficclass & 0x0f ) = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ( ipv6_buf - > trafficclass_flowlabel & 0xf0 ) = = 0 ) ) {
2012-11-05 22:29:11 +01:00
/* traffic class is elided */
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 0 ] | = SIXLOWPAN_IPHC1_TC_C ;
2012-11-05 22:29:11 +01:00
/* ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided */
2013-06-22 05:11:53 +02:00
ipv6_hdr_fields [ hdr_pos ] = ( ( tc & 0xc0 ) |
( ipv6_buf - > trafficclass_flowlabel & 0x0f ) ) ;
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_hdr_fields [ hdr_pos ] ) , & ipv6_buf - > flowlabel , 2 ) ;
2013-06-22 05:11:53 +02:00
hdr_pos + = 3 ;
}
else {
2012-11-05 22:29:11 +01:00
/* ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) */
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ipv6_buf - > version_trafficclass , 4 ) ;
ipv6_hdr_fields [ hdr_pos ] = tc ;
hdr_pos + = 4 ;
}
}
2013-06-22 05:11:53 +02:00
/* NH: Next Header:
2012-11-05 22:29:11 +01:00
* TODO : NHC */
ipv6_hdr_fields [ hdr_pos ] = ipv6_buf - > nextheader ;
hdr_pos + + ;
/* HLIM: Hop Limit: */
2013-08-08 13:39:00 +02:00
switch ( ipv6_buf - > hoplimit ) {
2013-06-24 22:37:35 +02:00
case ( 1 ) : {
2012-11-05 22:29:11 +01:00
/* 01: The Hop Limit field is compressed and the hop limit is 1. */
lowpan_iphc [ 0 ] | = 0x01 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 64 ) : {
2012-11-05 22:29:11 +01:00
/* 10: The Hop Limit field is compressed and the hop limit is 64. */
lowpan_iphc [ 0 ] | = 0x02 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 255 ) : {
2012-11-05 22:29:11 +01:00
/* 11: The Hop Limit field is compressed and the hop limit is 255. */
lowpan_iphc [ 0 ] | = 0x03 ;
break ;
}
2013-06-22 05:11:53 +02:00
default : {
2012-11-05 22:29:11 +01:00
ipv6_hdr_fields [ hdr_pos ] = ipv6_buf - > hoplimit ;
hdr_pos + + ;
break ;
}
}
mutex_lock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* CID: Context Identifier Extension: */
2013-06-24 22:37:35 +02:00
if ( ( lowpan_context_lookup ( & ipv6_buf - > srcaddr ) ! = NULL ) | |
2013-08-08 13:39:00 +02:00
( lowpan_context_lookup ( & ipv6_buf - > destaddr ) ! = NULL ) ) {
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 1 ] | = SIXLOWPAN_IPHC2_CID ;
2013-06-22 05:11:53 +02:00
memmove ( & ipv6_hdr_fields [ 1 ] , & ipv6_hdr_fields [ 0 ] , hdr_pos ) ;
2012-11-05 22:29:11 +01:00
hdr_pos + + ;
}
/* SAC: Source Address Compression */
2013-08-13 06:41:05 +02:00
if ( ipv6_addr_is_unspecified ( & ( ipv6_buf - > srcaddr ) ) ) {
2012-11-05 22:29:11 +01:00
/* SAC = 1 and SAM = 00 */
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 1 ] | = SIXLOWPAN_IPHC2_SAC ;
2013-06-22 05:11:53 +02:00
}
2013-06-24 22:37:35 +02:00
else if ( ( con = lowpan_context_lookup ( & ipv6_buf - > srcaddr ) ) ! = NULL ) {
2012-11-05 22:29:11 +01:00
/* 1: Source address compression uses stateful, context-based
* compression . */
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 1 ] | = SIXLOWPAN_IPHC2_SAC ;
2012-11-05 22:29:11 +01:00
ipv6_hdr_fields [ 0 ] | = ( con - > num < < 4 ) ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
if ( memcmp ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , & ( iface . laddr . uint8 [ 0 ] ) , 8 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* 0 bits. The address is derived using context information
* and possibly the link - layer addresses . */
lowpan_iphc [ 1 ] | = 0x30 ;
2013-06-22 05:11:53 +02:00
}
2013-06-24 22:37:35 +02:00
else if ( ( ipv6_buf - > srcaddr . uint16 [ 4 ] = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ipv6_buf - > srcaddr . uint16 [ 5 ] = = 0 ) & &
( ipv6_buf - > srcaddr . uint16 [ 6 ] = = 0 ) & &
( ( ipv6_buf - > srcaddr . uint8 [ 14 ] ) & 0x80 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* 49-bit of interface identifier are 0, so we can compress
* source address - iid to 16 - bit */
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ipv6_buf - > srcaddr . uint16 [ 7 ] , 2 ) ;
hdr_pos + = 2 ;
/* 16 bits. The address is derived using context information
* and the 16 bits carried inline . */
lowpan_iphc [ 1 ] | = 0x20 ;
2013-06-22 05:11:53 +02:00
}
else {
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ( ipv6_buf - > srcaddr . uint16 [ 4 ] ) , 8 ) ;
2012-11-05 22:29:11 +01:00
hdr_pos + = 8 ;
/* 64 bits. The address is derived using context information
2013-06-22 05:11:53 +02:00
* and the 64 bits carried inline . */
2012-11-05 22:29:11 +01:00
lowpan_iphc [ 1 ] | = 0x10 ;
2013-06-22 05:11:53 +02:00
}
}
2013-08-13 06:41:05 +02:00
else if ( ipv6_addr_is_link_local ( & ipv6_buf - > srcaddr ) ) {
2012-11-05 22:29:11 +01:00
/* 0: Source address compression uses stateless compression.*/
2013-06-24 22:37:35 +02:00
if ( memcmp ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , & ( iface . laddr . uint8 [ 0 ] ) , 8 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* 0 bits. The address is derived using context information
* and possibly the link - layer addresses . */
lowpan_iphc [ 1 ] | = 0x30 ;
2013-06-22 05:11:53 +02:00
}
2013-06-24 22:37:35 +02:00
else if ( ( ipv6_buf - > srcaddr . uint16 [ 4 ] = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ipv6_buf - > srcaddr . uint16 [ 5 ] = = 0 ) & &
( ipv6_buf - > srcaddr . uint16 [ 6 ] = = 0 ) & &
( ( ipv6_buf - > srcaddr . uint8 [ 14 ] ) & 0x80 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* 49-bit of interface identifier are 0, so we can compress
* source address - iid to 16 - bit */
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ipv6_buf - > srcaddr . uint16 [ 7 ] , 2 ) ;
hdr_pos + = 2 ;
/* 16 bits. The address is derived using context information
* and the 16 bits carried inline . */
lowpan_iphc [ 1 ] | = 0x20 ;
2013-06-22 05:11:53 +02:00
}
else {
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ( ipv6_buf - > srcaddr . uint16 [ 4 ] ) , 8 ) ;
2012-11-05 22:29:11 +01:00
hdr_pos + = 8 ;
/* 64 bits. The address is derived using context information
2013-06-22 05:11:53 +02:00
* and the 64 bits carried inline . */
2012-11-05 22:29:11 +01:00
lowpan_iphc [ 1 ] | = 0x10 ;
2013-06-22 05:11:53 +02:00
}
}
else {
2012-11-05 22:29:11 +01:00
/* full address carried inline */
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , 16 ) ;
hdr_pos + = 16 ;
}
/* M: Multicast Compression */
2013-08-13 06:41:05 +02:00
if ( ipv6_addr_is_multicast ( & ipv6_buf - > destaddr ) ) {
2012-11-05 22:29:11 +01:00
/* 1: Destination address is a multicast address. */
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 1 ] | = SIXLOWPAN_IPHC2_M ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* just another cool if condition */
2013-06-24 22:37:35 +02:00
if ( ( ipv6_buf - > destaddr . uint8 [ 1 ] = = 2 ) & &
2013-08-08 13:39:00 +02:00
( ipv6_buf - > destaddr . uint16 [ 1 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 2 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 3 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 4 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 5 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 6 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint8 [ 14 ] = = 0 ) ) {
2012-11-05 22:29:11 +01:00
/* 11: 8 bits. The address takes the form FF02::00XX. */
lowpan_iphc [ 1 ] | = 0x03 ;
ipv6_hdr_fields [ hdr_pos ] = ipv6_buf - > destaddr . uint8 [ 15 ] ;
hdr_pos + + ;
2013-06-22 05:11:53 +02:00
}
2013-06-24 22:37:35 +02:00
else if ( ( ipv6_buf - > destaddr . uint16 [ 1 ] = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ipv6_buf - > destaddr . uint16 [ 2 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 3 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 4 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 5 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint8 [ 12 ] = = 0 ) ) {
2012-11-05 22:29:11 +01:00
/* 10: 32 bits. The address takes the form FFXX::00XX:XXXX. */
lowpan_iphc [ 1 ] | = 0x02 ;
/* copy second and last 3 byte */
ipv6_hdr_fields [ hdr_pos ] = ipv6_buf - > destaddr . uint8 [ 1 ] ;
hdr_pos + + ;
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ipv6_buf - > destaddr . uint8 [ 13 ] , 3 ) ;
2013-06-22 05:11:53 +02:00
hdr_pos + = 3 ;
}
2013-06-24 22:37:35 +02:00
else if ( ( ipv6_buf - > destaddr . uint16 [ 1 ] = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ipv6_buf - > destaddr . uint16 [ 2 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 3 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 4 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint8 [ 10 ] = = 0 ) ) {
2012-11-05 22:29:11 +01:00
/* 01: 48 bits. The address takes the form FFXX::00XX:XXXX:XXXX */
lowpan_iphc [ 1 ] | = 0x01 ;
/* copy second and last 5 byte */
ipv6_hdr_fields [ hdr_pos ] = ipv6_buf - > destaddr . uint8 [ 1 ] ;
hdr_pos + + ;
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ipv6_buf - > destaddr . uint8 [ 11 ] , 5 ) ;
hdr_pos + = 5 ;
2013-06-22 05:11:53 +02:00
}
else {
2012-11-05 22:29:11 +01:00
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ipv6_buf - > destaddr . uint8 [ 0 ] , 16 ) ;
hdr_pos + = 16 ;
2013-06-22 05:11:53 +02:00
}
}
else {
2012-11-05 22:29:11 +01:00
/* 0: Destination address is not a multicast address. */
2013-06-24 22:37:35 +02:00
if ( ( con = lowpan_context_lookup ( & ipv6_buf - > destaddr ) ) ! = NULL ) {
2012-11-05 22:29:11 +01:00
/* 1: Destination address compression uses stateful, context-based
* compression . */
2013-08-09 03:13:37 +02:00
lowpan_iphc [ 1 ] | = SIXLOWPAN_IPHC2_DAC ;
2012-11-05 22:29:11 +01:00
ipv6_hdr_fields [ 0 ] = con - > num ;
2013-06-24 22:37:35 +02:00
if ( memcmp ( & ( ipv6_buf - > destaddr . uint8 [ 8 ] ) , & ( dest - > uint8 [ 0 ] ) , 8 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* 0 bits. The address is derived using context information
* and possibly the link - layer addresses . */
lowpan_iphc [ 1 ] | = 0x03 ;
2013-06-22 05:11:53 +02:00
}
2013-06-24 22:37:35 +02:00
else if ( ( ipv6_buf - > destaddr . uint16 [ 4 ] = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ipv6_buf - > destaddr . uint16 [ 5 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 6 ] = = 0 ) & &
( ( ipv6_buf - > destaddr . uint8 [ 14 ] ) & 0x80 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* 49-bit of interface identifier are 0, so we can compress
* source address - iid to 16 - bit */
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ipv6_buf - > destaddr . uint16 [ 7 ] , 2 ) ;
hdr_pos + = 2 ;
/* 16 bits. The address is derived using context information
* and the 16 bits carried inline . */
lowpan_iphc [ 1 ] | = 0x02 ;
2013-06-22 05:11:53 +02:00
}
else {
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ( ipv6_buf - > destaddr . uint16 [ 4 ] ) , 8 ) ;
2012-11-05 22:29:11 +01:00
hdr_pos + = 8 ;
/* 64 bits. The address is derived using context information
* and the 64 bits carried inline . */
lowpan_iphc [ 1 ] | = 0x01 ;
}
2013-06-22 05:11:53 +02:00
}
2013-08-13 06:41:05 +02:00
else if ( ipv6_addr_is_link_local ( & ipv6_buf - > destaddr ) ) {
2013-06-24 22:37:35 +02:00
if ( memcmp ( & ( ipv6_buf - > destaddr . uint8 [ 8 ] ) , & ( dest - > uint8 [ 0 ] ) , 8 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* 0 bits. The address is derived using context information
* and possibly the link - layer addresses . */
lowpan_iphc [ 1 ] | = 0x03 ;
2013-06-22 05:11:53 +02:00
}
2013-06-24 22:37:35 +02:00
else if ( ( ipv6_buf - > destaddr . uint16 [ 4 ] = = 0 ) & &
2013-08-08 13:39:00 +02:00
( ipv6_buf - > destaddr . uint16 [ 5 ] = = 0 ) & &
( ipv6_buf - > destaddr . uint16 [ 6 ] = = 0 ) & &
( ( ipv6_buf - > destaddr . uint8 [ 14 ] ) & 0x80 ) = = 0 ) {
2012-11-05 22:29:11 +01:00
/* 49-bit of interface identifier are 0, so we can compress
* source address - iid to 16 - bit */
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ipv6_buf - > destaddr . uint16 [ 7 ] , 2 ) ;
hdr_pos + = 2 ;
/* 16 bits. The address is derived using context information
* and the 16 bits carried inline . */
lowpan_iphc [ 1 ] | = 0x02 ;
2013-06-22 05:11:53 +02:00
}
else {
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ( ipv6_buf - > destaddr . uint16 [ 4 ] ) , 8 ) ;
2012-11-05 22:29:11 +01:00
hdr_pos + = 8 ;
/* 64 bits. The address is derived using context information
* and the 64 bits carried inline . */
lowpan_iphc [ 1 ] | = 0x01 ;
}
2013-06-22 05:11:53 +02:00
}
else {
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , 16 ) ;
2012-11-05 22:29:11 +01:00
hdr_pos + = 16 ;
}
}
2013-06-22 05:11:53 +02:00
2013-08-04 04:06:31 +02:00
mutex_unlock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
comp_buf [ 0 ] = lowpan_iphc [ 0 ] ;
comp_buf [ 1 ] = lowpan_iphc [ 1 ] ;
/*uint8_t *ptr;
2013-08-13 06:41:05 +02:00
if ( ipv6_buf - > nextheader = = IPV6_PROTO_NUM_TCP )
2013-06-22 05:11:53 +02:00
{
2012-11-05 22:29:11 +01:00
ptr = get_payload_buf_send ( ipv6_ext_hdr_len ) ;
2013-06-22 05:11:53 +02:00
}
2012-11-05 22:29:11 +01:00
else
2013-06-22 05:11:53 +02:00
{
2012-11-05 22:29:11 +01:00
ptr = get_payload_buf ( ipv6_ext_hdr_len ) ;
2013-06-22 05:11:53 +02:00
}
*/
memcpy ( & ipv6_hdr_fields [ hdr_pos ] , & ptr [ IPV6_HDR_LEN ] , ipv6_buf - > length ) ;
2012-11-05 22:29:11 +01:00
comp_len = 2 + hdr_pos + payload_length ;
}
2013-06-22 05:11:53 +02:00
void lowpan_iphc_decoding ( uint8_t * data , uint8_t length ,
ieee_802154_long_t * s_laddr ,
ieee_802154_long_t * d_laddr )
{
2012-11-05 22:29:11 +01:00
uint8_t hdr_pos = 0 ;
uint8_t * ipv6_hdr_fields = data ;
uint8_t lowpan_iphc [ 2 ] ;
uint8_t cid = 0 ;
uint8_t sci = 0 ;
uint8_t dci = 0 ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
uint8_t ll_prefix [ 2 ] = { 0xfe , 0x80 } ;
uint8_t m_prefix [ 2 ] = { 0xff , 0x02 } ;
lowpan_context_t * con = NULL ;
2013-06-22 05:11:53 +02:00
2013-08-13 06:41:05 +02:00
ipv6_buf = ipv6_get_buf ( ) ;
2012-11-05 22:29:11 +01:00
lowpan_iphc [ 0 ] = ipv6_hdr_fields [ 0 ] ;
lowpan_iphc [ 1 ] = ipv6_hdr_fields [ 1 ] ;
hdr_pos + = 2 ;
/* first check if CID flag is set */
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_CID ) {
2012-11-05 22:29:11 +01:00
hdr_pos + + ;
cid = 1 ;
}
/* TF: Traffic Class, Flow Label: */
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 0 ] & SIXLOWPAN_IPHC1_FL_C ) {
2012-11-05 22:29:11 +01:00
/* flowlabel is elided */
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 0 ] & SIXLOWPAN_IPHC1_TC_C ) {
2012-11-05 22:29:11 +01:00
/* traffic class is elided */
ipv6_buf - > version_trafficclass = 0x60 ;
ipv6_buf - > trafficclass_flowlabel = 0 ;
2013-06-22 05:11:53 +02:00
ipv6_buf - > flowlabel = 0 ;
}
else {
2012-11-05 22:29:11 +01:00
/* toogle ecn/dscp order */
2013-06-22 05:11:53 +02:00
ipv6_buf - > version_trafficclass = 0x60 | ( 0x0f &
2012-11-05 22:29:11 +01:00
( ipv6_hdr_fields [ hdr_pos ] > > 2 ) ) ;
ipv6_buf - > trafficclass_flowlabel = ( ( ipv6_hdr_fields [ hdr_pos ] > > 2 ) & 0x30 ) |
( ( ipv6_hdr_fields [ hdr_pos ] < < 6 ) & 0xc0 ) ;
2013-06-22 05:11:53 +02:00
ipv6_buf - > flowlabel = 0 ;
hdr_pos + = 3 ;
2012-11-05 22:29:11 +01:00
}
2013-06-22 05:11:53 +02:00
}
else {
2012-11-05 22:29:11 +01:00
/* flowlabel carried inline */
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 0 ] & SIXLOWPAN_IPHC1_TC_C ) {
2012-11-05 22:29:11 +01:00
/* traffic class is elided */
ipv6_buf - > version_trafficclass = 0x60 ;
/* ecn + 4 bit flowlabel*/
2013-06-22 05:11:53 +02:00
ipv6_buf - > trafficclass_flowlabel = ( ( ipv6_hdr_fields [ hdr_pos ] > > 2 ) & 0x30 ) |
( ipv6_hdr_fields [ hdr_pos ] & 0x0f ) ;
2012-11-05 22:29:11 +01:00
hdr_pos + + ;
/* copy 2byte flowlabel */
memcpy ( & ipv6_buf - > flowlabel , & ipv6_hdr_fields [ hdr_pos ] , 2 ) ;
2013-06-22 05:11:53 +02:00
hdr_pos + = 2 ;
}
else {
2012-11-05 22:29:11 +01:00
ipv6_buf - > version_trafficclass = 0x60 | ( 0x0f &
( ipv6_hdr_fields [ hdr_pos ] > > 2 ) ) ;
2013-06-22 05:11:53 +02:00
ipv6_buf - > trafficclass_flowlabel = ( ( ipv6_hdr_fields [ hdr_pos ] > > 2 ) & 0x30 ) |
( ipv6_hdr_fields [ hdr_pos ] & 0x0f ) |
( ipv6_hdr_fields [ hdr_pos + 1 ] & 0x0f ) ;
2012-11-05 22:29:11 +01:00
hdr_pos + = 2 ;
2013-06-22 05:11:53 +02:00
memcpy ( & ipv6_buf - > trafficclass_flowlabel ,
2012-11-05 22:29:11 +01:00
& ipv6_hdr_fields [ hdr_pos ] , 2 ) ;
2013-06-22 05:11:53 +02:00
hdr_pos + = 2 ;
2012-11-05 22:29:11 +01:00
}
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* NH: Next Header: */
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 0 ] & SIXLOWPAN_IPHC1_NH ) {
2012-11-05 22:29:11 +01:00
// TODO: next header decompression
2013-06-22 05:11:53 +02:00
}
else {
2012-11-05 22:29:11 +01:00
ipv6_buf - > nextheader = ipv6_hdr_fields [ hdr_pos ] ;
hdr_pos + + ;
}
/* HLIM: Hop Limit: */
2013-06-24 22:37:35 +02:00
if ( lowpan_iphc [ 0 ] & 0x03 ) {
2013-08-08 13:39:00 +02:00
switch ( lowpan_iphc [ 0 ] & 0x03 ) {
2013-06-24 22:37:35 +02:00
case ( 0x01 ) : {
2012-11-05 22:29:11 +01:00
ipv6_buf - > hoplimit = 1 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x02 ) : {
2012-11-05 22:29:11 +01:00
ipv6_buf - > hoplimit = 64 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x03 ) : {
2012-11-05 22:29:11 +01:00
ipv6_buf - > hoplimit = 255 ;
break ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
default :
break ;
2013-06-22 05:11:53 +02:00
}
}
else {
2012-11-05 22:29:11 +01:00
ipv6_buf - > hoplimit = ipv6_hdr_fields [ hdr_pos ] ;
hdr_pos + + ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* CID: Context Identifier Extension: + SAC: Source Address Compression */
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_SAC ) {
2012-11-05 22:29:11 +01:00
/* 1: Source address compression uses stateful, context-based
* compression . */
2013-06-24 22:37:35 +02:00
if ( cid ) {
2012-11-05 22:29:11 +01:00
sci = ipv6_hdr_fields [ 3 ] > > 4 ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
mutex_lock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* check context number */
2013-08-09 03:13:37 +02:00
if ( ( ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_SAM ) > > 4 ) & 0x03 ) {
2013-06-22 05:11:53 +02:00
con = lowpan_context_num_lookup ( sci ) ;
2012-11-05 22:29:11 +01:00
}
2013-06-24 22:37:35 +02:00
if ( con = = NULL ) {
2012-11-05 22:29:11 +01:00
printf ( " ERROR: context not found \n " ) ;
return ;
}
2013-06-22 05:11:53 +02:00
2013-08-09 03:13:37 +02:00
switch ( ( ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_SAM ) > > 4 ) & 0x03 ) {
2013-06-24 22:37:35 +02:00
case ( 0x01 ) : {
2012-11-05 22:29:11 +01:00
/* 64-bits */
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 8 ) ;
2013-06-22 05:11:53 +02:00
/* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context
* information are always used . */
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & con - > prefix , con - > length ) ;
hdr_pos + = 8 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x02 ) : {
2012-11-05 22:29:11 +01:00
/* 16-bits */
memset ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , 0 , 6 ) ;
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 14 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 2 ) ;
2013-06-22 05:11:53 +02:00
/* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context
* information are always used . */
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & con - > prefix , con - > length ) ;
hdr_pos + = 2 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x03 ) : {
2012-11-05 22:29:11 +01:00
/* 0-bits */
memset ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , 0 , 8 ) ;
2013-06-22 05:11:53 +02:00
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , & s_laddr - > uint8 [ 0 ] , 8 ) ;
/* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context
* information are always used . */
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & con - > prefix , con - > length ) ;
break ;
}
2013-06-22 05:11:53 +02:00
default : {
2012-11-05 22:29:11 +01:00
/* unspecified address */
memset ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , 0 , 16 ) ;
break ;
}
}
2013-06-22 05:11:53 +02:00
2013-08-04 04:06:31 +02:00
mutex_unlock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
}
else {
2013-08-09 03:13:37 +02:00
switch ( ( ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_SAM ) > > 4 ) & 0x03 ) {
2013-06-24 22:37:35 +02:00
case ( 0x01 ) : {
2012-11-05 22:29:11 +01:00
/* 64-bits */
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & ll_prefix [ 0 ] , 2 ) ;
memset ( & ( ipv6_buf - > srcaddr . uint8 [ 2 ] ) , 0 , 6 ) ;
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 8 ) ;
hdr_pos + = 8 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x02 ) : {
2012-11-05 22:29:11 +01:00
/* 16-bits */
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & ll_prefix [ 0 ] , 2 ) ;
memset ( & ( ipv6_buf - > srcaddr . uint8 [ 2 ] ) , 0 , 12 ) ;
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 14 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 2 ) ;
hdr_pos + = 2 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x03 ) : {
2012-11-05 22:29:11 +01:00
/* 0-bits */
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & ll_prefix [ 0 ] , 2 ) ;
memset ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , 0 , 14 ) ;
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 8 ] ) , & s_laddr - > uint8 [ 0 ] , 8 ) ;
break ;
}
2013-06-22 05:11:53 +02:00
default : {
2012-11-05 22:29:11 +01:00
/* full address carried inline */
2013-06-22 05:11:53 +02:00
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) ,
2012-11-05 22:29:11 +01:00
& ipv6_hdr_fields [ hdr_pos ] , 16 ) ;
hdr_pos + = 16 ;
break ;
}
}
}
/* M: Multicast Compression + DAC: Destination Address Compression */
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_M ) {
2012-11-05 22:29:11 +01:00
/* 1: Destination address is a multicast address. */
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_DAC ) {
2012-11-05 22:29:11 +01:00
/* 1: Destination address compression uses stateful, context-based
2013-06-22 05:11:53 +02:00
* compression .
* If M = 1 and DAC = 1 : */
2013-06-24 22:37:35 +02:00
if ( cid ) {
2012-11-05 22:29:11 +01:00
dci = ipv6_hdr_fields [ 3 ] & 0x0f ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
mutex_lock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
2013-08-09 03:13:37 +02:00
if ( ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_DAM ) & 0x03 ) {
2013-06-22 05:11:53 +02:00
con = lowpan_context_num_lookup ( dci ) ;
2012-11-05 22:29:11 +01:00
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
if ( con = = NULL ) {
2012-11-05 22:29:11 +01:00
printf ( " ERROR: context not found \n " ) ;
return ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
// TODO:
2013-08-04 04:06:31 +02:00
mutex_unlock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
}
else {
2012-11-05 22:29:11 +01:00
/* If M=1 and DAC=0: */
2013-08-08 13:39:00 +02:00
switch ( lowpan_iphc [ 1 ] & 0x03 ) {
2013-06-24 22:37:35 +02:00
case ( 0x01 ) : {
2012-11-05 22:29:11 +01:00
m_prefix [ 1 ] = ipv6_hdr_fields [ hdr_pos ] ;
hdr_pos + + ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x02 ) : {
2012-11-05 22:29:11 +01:00
m_prefix [ 1 ] = ipv6_hdr_fields [ hdr_pos ] ;
hdr_pos + + ;
break ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
default :
break ;
}
2013-06-22 05:11:53 +02:00
2013-08-08 13:39:00 +02:00
switch ( lowpan_iphc [ 1 ] & 0x03 ) {
2013-06-24 22:37:35 +02:00
case ( 0x01 ) : {
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , & m_prefix [ 0 ] , 2 ) ;
memset ( & ( ipv6_buf - > destaddr . uint8 [ 2 ] ) , 0 , 9 ) ;
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 11 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 5 ) ;
hdr_pos + = 5 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x02 ) : {
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , & m_prefix [ 0 ] , 2 ) ;
memset ( & ( ipv6_buf - > destaddr . uint8 [ 2 ] ) , 0 , 11 ) ;
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 13 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 3 ) ;
hdr_pos + = 3 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x03 ) : {
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , & m_prefix [ 0 ] , 2 ) ;
memset ( & ( ipv6_buf - > destaddr . uint8 [ 2 ] ) , 0 , 13 ) ;
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 15 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 1 ) ;
hdr_pos + + ;
break ;
}
2013-06-22 05:11:53 +02:00
default : {
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 16 ) ;
break ;
}
2013-06-22 05:11:53 +02:00
}
2012-11-05 22:29:11 +01:00
}
2013-06-22 05:11:53 +02:00
}
else {
2013-08-09 03:13:37 +02:00
if ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_DAC ) {
2012-11-05 22:29:11 +01:00
/* 1: Destination address compression uses stateful, context-based
2013-06-22 05:11:53 +02:00
* compression .
2012-11-05 22:29:11 +01:00
* If M = 1 and DAC = 1 : */
2013-06-24 22:37:35 +02:00
if ( cid ) {
2012-11-05 22:29:11 +01:00
dci = ipv6_hdr_fields [ 3 ] & 0x0f ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
mutex_lock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
2013-08-09 03:13:37 +02:00
if ( ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_DAM ) & 0x03 ) {
2012-11-05 22:29:11 +01:00
con = lowpan_context_num_lookup ( dci ) ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
if ( con = = NULL ) {
2012-11-05 22:29:11 +01:00
printf ( " ERROR: context not found \n " ) ;
return ;
}
2013-06-22 05:11:53 +02:00
2013-08-09 03:13:37 +02:00
switch ( ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_DAM ) & 0x03 ) {
2013-06-24 22:37:35 +02:00
case ( 0x01 ) : {
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 8 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 8 ) ;
/* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context information are always used. */
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & con - > prefix , con - > length ) ;
hdr_pos + = 8 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x02 ) : {
2012-11-05 22:29:11 +01:00
memset ( & ( ipv6_buf - > destaddr . uint8 [ 8 ] ) , 0 , 6 ) ;
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 14 ] ) , & ipv6_hdr_fields [ hdr_pos ] , 2 ) ;
/* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context information are always used. */
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & con - > prefix , con - > length ) ;
hdr_pos + = 2 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x03 ) : {
2012-11-05 22:29:11 +01:00
memset ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , 0 , 8 ) ;
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 8 ] ) , & d_laddr - > uint8 [ 0 ] , 8 ) ;
/* By draft-ietf-6lowpan-hc-15 3.1.1. Bits covered by context information are always used. */
memcpy ( & ( ipv6_buf - > srcaddr . uint8 [ 0 ] ) , & con - > prefix , con - > length ) ;
break ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
default :
break ;
}
2013-06-22 05:11:53 +02:00
2013-08-04 04:06:31 +02:00
mutex_unlock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
}
else {
2013-08-09 03:13:37 +02:00
switch ( ( lowpan_iphc [ 1 ] & SIXLOWPAN_IPHC2_DAM ) & 0x03 ) {
2013-06-24 22:37:35 +02:00
case ( 0x01 ) : {
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , & ll_prefix [ 0 ] , 2 ) ;
memset ( & ( ipv6_buf - > destaddr . uint8 [ 2 ] ) , 0 , 6 ) ;
2013-06-22 05:11:53 +02:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 8 ] ) ,
2012-11-05 22:29:11 +01:00
& ipv6_hdr_fields [ hdr_pos ] , 8 ) ;
hdr_pos + = 8 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x02 ) : {
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , & ll_prefix [ 0 ] , 2 ) ;
memset ( & ( ipv6_buf - > destaddr . uint8 [ 2 ] ) , 0 , 12 ) ;
2013-06-22 05:11:53 +02:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 14 ] ) ,
2012-11-05 22:29:11 +01:00
& ipv6_hdr_fields [ hdr_pos ] , 2 ) ;
hdr_pos + = 2 ;
break ;
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
case ( 0x03 ) : {
2012-11-05 22:29:11 +01:00
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) , & ll_prefix , 2 ) ;
memset ( & ( ipv6_buf - > destaddr . uint8 [ 2 ] ) , 0 , 14 ) ;
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 8 ] ) , & d_laddr - > uint8 [ 0 ] , 8 ) ;
break ;
}
2013-06-22 05:11:53 +02:00
default : {
memcpy ( & ( ipv6_buf - > destaddr . uint8 [ 0 ] ) ,
2012-11-05 22:29:11 +01:00
& ipv6_hdr_fields [ hdr_pos ] , 16 ) ;
2013-06-22 05:11:53 +02:00
hdr_pos + = 16 ;
2012-11-05 22:29:11 +01:00
break ;
}
2013-06-22 05:11:53 +02:00
}
}
2012-11-05 22:29:11 +01:00
}
uint8_t * ptr = get_payload_buf ( ipv6_ext_hdr_len ) ;
memcpy ( ptr , & ipv6_hdr_fields [ hdr_pos ] , length - hdr_pos ) ;
/* ipv6 length */
ipv6_buf - > length = length - hdr_pos ;
2013-06-22 05:11:53 +02:00
packet_length = IPV6_HDR_LEN + ipv6_buf - > length ;
2012-11-05 22:29:11 +01:00
}
2013-06-22 05:11:53 +02:00
uint8_t lowpan_context_len ( )
{
2012-11-05 22:29:11 +01:00
return context_len ;
}
2013-06-22 05:11:53 +02:00
void lowpan_context_remove ( uint8_t num )
{
int i , j ;
2013-08-14 04:35:58 +02:00
for ( i = 0 ; i < NDP_6LOWPAN_CONTEXT_MAX ; i + + ) {
2013-06-24 22:37:35 +02:00
if ( contexts [ i ] . num = = num ) {
2012-11-05 22:29:11 +01:00
context_len - - ;
break ;
}
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
abr_remove_context ( num ) ;
2013-06-22 05:11:53 +02:00
2013-08-14 04:35:58 +02:00
for ( j = i ; j < NDP_6LOWPAN_CONTEXT_MAX ; j + + ) {
2013-06-22 05:11:53 +02:00
contexts [ j ] = contexts [ j + 1 ] ;
2012-11-05 22:29:11 +01:00
}
}
2013-06-22 05:11:53 +02:00
lowpan_context_t * lowpan_context_update ( uint8_t num , const ipv6_addr_t * prefix ,
uint8_t length , uint8_t comp ,
uint16_t lifetime )
{
2012-11-05 22:29:11 +01:00
lowpan_context_t * context ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
if ( lifetime = = 0 ) {
2012-11-05 22:29:11 +01:00
lowpan_context_remove ( num ) ;
return NULL ;
}
2013-06-22 05:11:53 +02:00
2013-08-14 04:35:58 +02:00
if ( context_len = = NDP_6LOWPAN_CONTEXT_MAX ) {
2012-11-05 22:29:11 +01:00
return NULL ;
2013-06-22 05:11:53 +02:00
}
2012-11-05 22:29:11 +01:00
context = lowpan_context_num_lookup ( num ) ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
if ( context = = NULL ) {
2012-11-05 22:29:11 +01:00
context = & ( contexts [ context_len + + ] ) ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
context - > num = num ;
2013-06-22 05:11:53 +02:00
memset ( ( void * ) ( & context - > prefix ) , 0 , 16 ) ;
2012-11-05 22:29:11 +01:00
// length in bits
2013-06-22 05:11:53 +02:00
memcpy ( ( void * ) ( & context - > prefix ) , ( void * ) prefix , length / 8 ) ;
2012-11-05 22:29:11 +01:00
context - > length = length ;
context - > comp = comp ;
context - > lifetime = lifetime ;
return context ;
}
2013-06-22 05:11:53 +02:00
lowpan_context_t * lowpan_context_get ( )
{
2012-11-05 22:29:11 +01:00
return contexts ;
}
2013-06-22 05:11:53 +02:00
lowpan_context_t * lowpan_context_lookup ( ipv6_addr_t * addr )
{
2012-11-05 22:29:11 +01:00
int i ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
lowpan_context_t * context = NULL ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
for ( i = 0 ; i < lowpan_context_len ( ) ; i + + ) {
if ( contexts [ i ] . length > 0 & & memcmp ( ( void * ) addr , & ( contexts [ i ] . prefix ) ,
2013-08-08 13:39:00 +02:00
contexts [ i ] . length ) = = 0 ) {
2013-06-22 05:11:53 +02:00
/* longer prefixes are always prefered */
2013-06-24 22:37:35 +02:00
if ( context = = NULL | | context - > length < contexts [ i ] . length ) {
2012-11-05 22:29:11 +01:00
context = & contexts [ i ] ;
}
}
}
2013-06-22 05:11:53 +02:00
return context ;
2012-11-05 22:29:11 +01:00
}
2013-06-22 05:11:53 +02:00
lowpan_context_t * lowpan_context_num_lookup ( uint8_t num )
{
2012-11-05 22:29:11 +01:00
int i ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
for ( i = 0 ; i < lowpan_context_len ( ) ; i + + ) {
if ( contexts [ i ] . num = = num ) {
2012-11-05 22:29:11 +01:00
return & contexts [ i ] ;
}
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
return NULL ;
}
2013-06-22 05:11:53 +02:00
void lowpan_context_auto_remove ( void )
{
timex_t minute = timex_set ( 60 , 0 ) ;
2012-11-05 22:29:11 +01:00
int i ;
2013-08-14 04:35:58 +02:00
int8_t to_remove [ NDP_6LOWPAN_CONTEXT_MAX ] ;
2012-11-05 22:29:11 +01:00
int8_t to_remove_size ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
while ( 1 ) {
2012-11-05 22:29:11 +01:00
vtimer_sleep ( minute ) ;
to_remove_size = 0 ;
mutex_lock ( & lowpan_context_mutex ) ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
for ( i = 0 ; i < lowpan_context_len ( ) ; i + + ) {
if ( - - ( contexts [ i ] . lifetime ) = = 0 ) {
2012-11-05 22:29:11 +01:00
to_remove [ to_remove_size + + ] = contexts [ i ] . num ;
}
}
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
for ( i = 0 ; i < to_remove_size ; i + + ) {
2012-11-05 22:29:11 +01:00
lowpan_context_remove ( to_remove [ i ] ) ;
}
2013-06-22 05:11:53 +02:00
2013-08-04 04:06:31 +02:00
mutex_unlock ( & lowpan_context_mutex ) ;
2012-11-05 22:29:11 +01:00
}
}
2013-06-22 05:11:53 +02:00
void init_reas_bufs ( lowpan_reas_buf_t * buf )
{
2013-08-13 06:41:05 +02:00
memset ( & buf - > s_laddr , 0 , IPV6_LL_ADDR_LEN ) ;
memset ( & buf - > d_laddr , 0 , IPV6_LL_ADDR_LEN ) ;
2013-06-22 05:11:53 +02:00
buf - > ident_no = 0 ;
buf - > timestamp = 0 ;
buf - > packet_size = 0 ;
buf - > current_packet_size = 0 ;
buf - > packet = NULL ;
buf - > interval_list_head = NULL ;
buf - > next = NULL ;
2012-11-05 22:29:11 +01:00
}
2013-08-09 03:13:37 +02:00
void sixlowpan_lowpan_init ( transceiver_type_t trans , uint8_t r_addr ,
int as_border )
2013-10-28 23:35:48 +01:00
{
lowpan_init ( trans , r_addr , NULL , 0 ) ;
}
void sixlowpan_lowpan_adhoc_init ( transceiver_type_t trans ,
const ipv6_addr_t * prefix ,
uint8_t r_addr )
{
lowpan_init ( trans , r_addr , prefix , 0 ) ;
}
void lowpan_init ( transceiver_type_t trans , uint8_t r_addr ,
const ipv6_addr_t * prefix , int as_border )
2013-06-22 05:11:53 +02:00
{
2012-11-05 22:29:11 +01:00
ipv6_addr_t tmp ;
2013-07-27 15:04:51 +02:00
short i ;
2012-11-05 22:29:11 +01:00
/* init mac-layer and radio transceiver */
2013-08-08 16:22:37 +02:00
sixlowpan_mac_init ( trans ) ;
2012-11-05 22:29:11 +01:00
/* init interface addresses */
2013-06-22 05:11:53 +02:00
memset ( & iface , 0 , sizeof ( iface_t ) ) ;
2013-08-08 16:22:37 +02:00
sixlowpan_mac_set_radio_address ( r_addr ) ;
sixlowpan_mac_init_802154_short_addr ( & ( iface . saddr ) ) ;
sixlowpan_mac_init_802154_long_addr ( & ( iface . laddr ) ) ;
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
/* init lowpan context mutex */
mutex_init ( & lowpan_context_mutex ) ;
/* init packet_fifo mutex */
mutex_init ( & fifo_mutex ) ;
local_address = r_addr ;
2013-10-28 23:35:48 +01:00
/* if prefix is set */
if ( prefix ! = NULL ) {
/* init network prefix */
ipv6_addr_t save_prefix ;
ipv6_addr_init_prefix ( & save_prefix , prefix , 64 ) ;
plist_add ( & save_prefix , 64 , NDP_OPT_PI_VLIFETIME_INFINITE , 0 , 1 ,
ICMPV6_NDP_OPT_PI_FLAG_AUTONOM ) ;
ipv6_init_iface_as_router ( ) ;
/* add global address */
ipv6_addr_set_by_eui64 ( & tmp , prefix ) ;
DEBUG ( " %s, %d: set unique address to %s, according to prefix %s \n " , __FILE__ , __LINE__ , ipv6_addr_to_str ( addr_str , & tmp ) , ipv6_addr_to_str ( addr_str , prefix ) ) ;
ipv6_iface_add_addr ( & tmp , IPV6_ADDR_TYPE_GLOBAL ,
NDP_ADDR_STATE_PREFERRED , 0 , 0 ) ;
}
DEBUG ( " %s, %d: set link local prefix to %s \n " , __FILE__ , __LINE__ , ipv6_addr_to_str ( addr_str , & lladdr ) ) ;
2012-11-05 22:29:11 +01:00
/* init link-local address */
2013-08-13 06:41:05 +02:00
ipv6_addr_set_link_local_prefix ( & lladdr ) ;
2013-06-22 05:11:53 +02:00
2013-10-28 23:35:48 +01:00
/* add link local address */
2012-11-05 22:29:11 +01:00
memcpy ( & ( lladdr . uint8 [ 8 ] ) , & ( iface . laddr . uint8 [ 0 ] ) , 8 ) ;
2013-10-28 23:35:48 +01:00
DEBUG ( " %s, %d: sixlowpan_lowpan_init(): add link local address: %s \n " , __FILE__ , __LINE__ , ipv6_addr_to_str ( addr_str , & lladdr ) ) ;
2013-08-13 06:41:05 +02:00
ipv6_iface_add_addr ( & lladdr , IPV6_ADDR_TYPE_LINK_LOCAL ,
NDP_ADDR_STATE_PREFERRED , 0 , 0 ) ;
2013-10-28 23:35:48 +01:00
/* add loopback address */
2013-08-13 06:41:05 +02:00
ipv6_addr_set_loopback_addr ( & tmp ) ;
2013-10-28 23:35:48 +01:00
DEBUG ( " %s, %d: sixlowpan_lowpan_init(): add loopback address: %s \n " , __FILE__ , __LINE__ , ipv6_addr_to_str ( addr_str , & tmp ) ) ;
2013-08-13 06:41:05 +02:00
ipv6_iface_add_addr ( & tmp , IPV6_ADDR_TYPE_LOOPBACK ,
NDP_ADDR_STATE_PREFERRED , 0 , 0 ) ;
2013-10-28 23:35:48 +01:00
/* add all nodes multicast address */
DEBUG ( " %s, %d: sixlowpan_lowpan_init(): add all nodes multicast address: %s \n " , __FILE__ , __LINE__ , ipv6_addr_to_str ( addr_str , & tmp ) ) ;
ipv6_iface_add_addr ( & tmp , IPV6_ADDR_TYPE_LOOPBACK ,
2013-08-13 06:41:05 +02:00
NDP_ADDR_STATE_PREFERRED , 0 , 0 ) ;
2013-06-22 05:11:53 +02:00
2013-06-24 22:37:35 +02:00
if ( as_border ) {
2013-06-22 05:11:53 +02:00
ip_process_pid = thread_create ( ip_process_buf , IP_PROCESS_STACKSIZE ,
PRIORITY_MAIN - 1 , CREATE_STACKTEST ,
border_process_lowpan ,
" border_process_lowpan " ) ;
}
else {
ip_process_pid = thread_create ( ip_process_buf , IP_PROCESS_STACKSIZE ,
PRIORITY_MAIN - 1 , CREATE_STACKTEST ,
2012-11-05 22:29:11 +01:00
ipv6_process , " ip_process " ) ;
}
2013-06-22 05:11:53 +02:00
2012-11-05 22:29:11 +01:00
nd_nbr_cache_rem_pid = thread_create ( nc_buf , NC_STACKSIZE ,
2013-06-22 05:11:53 +02:00
PRIORITY_MAIN - 1 , CREATE_STACKTEST ,
2012-11-05 22:29:11 +01:00
nbr_cache_auto_rem , " nbr_cache_rem " ) ;
2013-06-22 05:11:53 +02:00
contexts_rem_pid = thread_create ( con_buf , CON_STACKSIZE ,
PRIORITY_MAIN + 1 , CREATE_STACKTEST ,
2012-11-05 22:29:11 +01:00
lowpan_context_auto_remove , " lowpan_context_rem " ) ;
transfer_pid = thread_create ( lowpan_transfer_buf , LOWPAN_TRANSFER_BUF_STACKSIZE ,
2013-06-22 05:11:53 +02:00
PRIORITY_MAIN - 1 , CREATE_STACKTEST ,
lowpan_transfer , " lowpan_transfer " ) ;
2013-07-27 15:04:51 +02:00
for ( i = 0 ; i < SIXLOWIP_MAX_REGISTERED ; i + + ) {
sixlowip_reg [ i ] = 0 ;
}
2012-11-05 22:29:11 +01:00
}
2013-08-13 06:41:05 +02:00
void sixlowpan_lowpan_bootstrapping ( void )
{
2013-08-14 04:35:58 +02:00
icmpv6_send_router_sol ( OPT_SLLAO ) ;
2013-08-13 06:41:05 +02:00
}