Contiki 2.6

sicslowpan.c

Go to the documentation of this file.
00001 /**
00002  * \addtogroup sicslowpan
00003  * @{
00004  */
00005 /*
00006  * Copyright (c) 2008, Swedish Institute of Computer Science.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  * 3. Neither the name of the Institute nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * This file is part of the Contiki operating system.
00034  *
00035  * $Id: sicslowpan.c,v 1.52 2011/01/04 20:22:21 joxe Exp $
00036  */
00037 /**
00038  * \file
00039  *         6lowpan implementation (RFC4944 and draft-ietf-6lowpan-hc-06)
00040  *
00041  * \author Adam Dunkels <adam@sics.se>
00042  * \author Nicolas Tsiftes <nvt@sics.se>
00043  * \author Niclas Finne <nfi@sics.se>
00044  * \author Mathilde Durvy <mdurvy@cisco.com>
00045  * \author Julien Abeille <jabeille@cisco.com>
00046  * \author Joakim Eriksson <joakime@sics.se>
00047  * \author Joel Hoglund <joel@sics.se>
00048  */
00049 
00050 /**
00051  * FOR HC-06 COMPLIANCE TODO:
00052  * -Add compression options to UDP, currently only supports
00053  *  both ports compressed or both ports elided
00054  *  
00055  * -Verify TC/FL compression works
00056  *  
00057  * -Add stateless multicast option
00058  */
00059 
00060 #include <string.h>
00061 
00062 #include "contiki.h"
00063 #include "dev/watchdog.h"
00064 #include "net/tcpip.h"
00065 #include "net/uip.h"
00066 #include "net/uip-ds6.h"
00067 #include "net/rime.h"
00068 #include "net/sicslowpan.h"
00069 #include "net/neighbor-info.h"
00070 #include "net/netstack.h"
00071 
00072 #define DEBUG 0
00073 #if DEBUG
00074 /* PRINTFI and PRINTFO are defined for input and output to debug one without changing the timing of the other */
00075 uint8_t p;
00076 #include <stdio.h>
00077 #define PRINTF(...) printf(__VA_ARGS__)
00078 #define PRINTFI(...) printf(__VA_ARGS__)
00079 #define PRINTFO(...) printf(__VA_ARGS__)
00080 #define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
00081 #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])
00082 #define PRINTPACKETBUF() PRINTF("RIME buffer: "); for(p = 0; p < packetbuf_datalen(); p++){PRINTF("%.2X", *(rime_ptr + p));} PRINTF("\n")
00083 #define PRINTUIPBUF() PRINTF("UIP buffer: "); for(p = 0; p < uip_len; p++){PRINTF("%.2X", uip_buf[p]);}PRINTF("\n")
00084 #define PRINTSICSLOWPANBUF() PRINTF("SICSLOWPAN buffer: "); for(p = 0; p < sicslowpan_len; p++){PRINTF("%.2X", sicslowpan_buf[p]);}PRINTF("\n")
00085 #else
00086 #define PRINTF(...)
00087 #define PRINTFI(...)
00088 #define PRINTFO(...)
00089 #define PRINT6ADDR(addr)
00090 #define PRINTLLADDR(lladdr)
00091 #define PRINTPACKETBUF()
00092 #define PRINTUIPBUF()
00093 #define PRINTSICSLOWPANBUF()
00094 #endif /* DEBUG == 1*/
00095 
00096 #if UIP_LOGGING
00097 #include <stdio.h>
00098 void uip_log(char *msg);
00099 #define UIP_LOG(m) uip_log(m)
00100 #else
00101 #define UIP_LOG(m)
00102 #endif /* UIP_LOGGING == 1 */
00103 
00104 #ifdef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS
00105 #define SICSLOWPAN_MAX_MAC_TRANSMISSIONS SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS
00106 #else
00107 #define SICSLOWPAN_MAX_MAC_TRANSMISSIONS 4
00108 #endif
00109 
00110 #ifndef SICSLOWPAN_COMPRESSION
00111 #ifdef SICSLOWPAN_CONF_COMPRESSION
00112 #define SICSLOWPAN_COMPRESSION SICSLOWPAN_CONF_COMPRESSION
00113 #else
00114 #define SICSLOWPAN_COMPRESSION SICSLOWPAN_COMPRESSION_IPV6
00115 #endif /* SICSLOWPAN_CONF_COMPRESSION */
00116 #endif /* SICSLOWPAN_COMPRESSION */
00117 
00118 #ifndef SICSLOWPAN_CONF_NEIGHBOR_INFO
00119 /* Default is to use neighbor info updates if using RPL */
00120 #define SICSLOWPAN_CONF_NEIGHBOR_INFO UIP_CONF_IPV6_RPL
00121 #endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */
00122 
00123 #define GET16(ptr,index) (((uint16_t)((ptr)[index] << 8)) | ((ptr)[(index) + 1]))
00124 #define SET16(ptr,index,value) do {     \
00125   (ptr)[index] = ((value) >> 8) & 0xff; \
00126   (ptr)[index + 1] = (value) & 0xff;    \
00127 } while(0)
00128 
00129 /** \name Pointers in the rime buffer
00130  *  @{
00131  */
00132 #define RIME_FRAG_PTR           (rime_ptr)
00133 #define RIME_FRAG_DISPATCH_SIZE 0   /* 16 bit */
00134 #define RIME_FRAG_TAG           2   /* 16 bit */
00135 #define RIME_FRAG_OFFSET        4   /* 8 bit */
00136 
00137 /* define the buffer as a byte array */
00138 #define RIME_IPHC_BUF              ((uint8_t *)(rime_ptr + rime_hdr_len))
00139 
00140 #define RIME_HC1_PTR            (rime_ptr + rime_hdr_len)
00141 #define RIME_HC1_DISPATCH       0 /* 8 bit */
00142 #define RIME_HC1_ENCODING       1 /* 8 bit */
00143 #define RIME_HC1_TTL            2 /* 8 bit */
00144 
00145 #define RIME_HC1_HC_UDP_PTR           (rime_ptr + rime_hdr_len)
00146 #define RIME_HC1_HC_UDP_DISPATCH      0 /* 8 bit */
00147 #define RIME_HC1_HC_UDP_HC1_ENCODING  1 /* 8 bit */
00148 #define RIME_HC1_HC_UDP_UDP_ENCODING  2 /* 8 bit */
00149 #define RIME_HC1_HC_UDP_TTL           3 /* 8 bit */
00150 #define RIME_HC1_HC_UDP_PORTS         4 /* 8 bit */
00151 #define RIME_HC1_HC_UDP_CHKSUM        5 /* 16 bit */
00152 
00153 /** \name Pointers in the sicslowpan and uip buffer
00154  *  @{
00155  */
00156 #define SICSLOWPAN_IP_BUF   ((struct uip_ip_hdr *)&sicslowpan_buf[UIP_LLH_LEN])
00157 #define SICSLOWPAN_UDP_BUF ((struct uip_udp_hdr *)&sicslowpan_buf[UIP_LLIPH_LEN])
00158 
00159 #define UIP_IP_BUF          ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
00160 #define UIP_UDP_BUF          ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
00161 #define UIP_TCP_BUF          ((struct uip_tcp_hdr *)&uip_buf[UIP_LLIPH_LEN])
00162 #define UIP_ICMP_BUF          ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN])
00163 /** @} */
00164 
00165 
00166 /** \brief Size of the 802.15.4 payload (127byte - 25 for MAC header) */
00167 #define MAC_MAX_PAYLOAD 102
00168 
00169 
00170 /** \brief Some MAC layers need a minimum payload, which is
00171     configurable through the SICSLOWPAN_CONF_MIN_MAC_PAYLOAD
00172     option. */
00173 #ifdef SICSLOWPAN_CONF_COMPRESSION_THRESHOLD
00174 #define COMPRESSION_THRESHOLD SICSLOWPAN_CONF_COMPRESSION_THRESHOLD
00175 #else
00176 #define COMPRESSION_THRESHOLD 0
00177 #endif
00178 
00179 /** \name General variables
00180  *  @{
00181  */
00182 #ifdef SICSLOWPAN_NH_COMPRESSOR
00183 /** A pointer to the additional compressor */
00184 extern struct sicslowpan_nh_compressor SICSLOWPAN_NH_COMPRESSOR;
00185 #endif
00186 
00187 /**
00188  * A pointer to the rime buffer.
00189  * We initialize it to the beginning of the rime buffer, then
00190  * access different fields by updating the offset rime_hdr_len.
00191  */
00192 static uint8_t *rime_ptr;
00193 
00194 /**
00195  * rime_hdr_len is the total length of (the processed) 6lowpan headers
00196  * (fragment headers, IPV6 or HC1, HC2, and HC1 and HC2 non compressed
00197  * fields).
00198  */
00199 static uint8_t rime_hdr_len;
00200 
00201 /**
00202  * The length of the payload in the Rime buffer.
00203  * The payload is what comes after the compressed or uncompressed
00204  * headers (can be the IP payload if the IP header only is compressed
00205  * or the UDP payload if the UDP header is also compressed)
00206  */
00207 static uint8_t rime_payload_len;
00208 
00209 /**
00210  * uncomp_hdr_len is the length of the headers before compression (if HC2
00211  * is used this includes the UDP header in addition to the IP header).
00212  */
00213 static uint8_t uncomp_hdr_len;
00214 
00215 /**
00216  * the result of the last transmitted fragment
00217  */
00218 static int last_tx_status;
00219 /** @} */
00220 
00221 #if SICSLOWPAN_CONF_FRAG
00222 /** \name Fragmentation related variables
00223  *  @{
00224  */
00225 
00226 static uint16_t sicslowpan_len;
00227 
00228 /**
00229  * The buffer used for the 6lowpan reassembly.
00230  * This buffer contains only the IPv6 packet (no MAC header, 6lowpan, etc).
00231  * It has a fix size as we do not use dynamic memory allocation.
00232  */
00233 static uip_buf_t sicslowpan_aligned_buf;
00234 #define sicslowpan_buf (sicslowpan_aligned_buf.u8)
00235 
00236 /** The total length of the IPv6 packet in the sicslowpan_buf. */
00237 
00238 /**
00239  * length of the ip packet already sent / received.
00240  * It includes IP and transport headers.
00241  */
00242 static uint16_t processed_ip_in_len;
00243 
00244 /** Datagram tag to be put in the fragments I send. */
00245 static uint16_t my_tag;
00246 
00247 /** When reassembling, the tag in the fragments being merged. */
00248 static uint16_t reass_tag;
00249 
00250 /** When reassembling, the source address of the fragments being merged */
00251 rimeaddr_t frag_sender;
00252 
00253 /** Reassembly %process %timer. */
00254 static struct timer reass_timer;
00255 
00256 /** @} */
00257 #else /* SICSLOWPAN_CONF_FRAG */
00258 /** The buffer used for the 6lowpan processing is uip_buf.
00259     We do not use any additional buffer.*/
00260 #define sicslowpan_buf uip_buf
00261 #define sicslowpan_len uip_len
00262 #endif /* SICSLOWPAN_CONF_FRAG */
00263 
00264 /*-------------------------------------------------------------------------*/
00265 /* Rime Sniffer support for one single listener to enable powertrace of IP */
00266 /*-------------------------------------------------------------------------*/
00267 static struct rime_sniffer *callback = NULL;
00268 
00269 void
00270 rime_sniffer_add(struct rime_sniffer *s)
00271 {
00272   callback = s;
00273 }
00274 
00275 void
00276 rime_sniffer_remove(struct rime_sniffer *s)
00277 {
00278   callback = NULL;
00279 }
00280 
00281 static void
00282 set_packet_attrs()
00283 {
00284   int c = 0;
00285   /* set protocol in NETWORK_ID */
00286   packetbuf_set_attr(PACKETBUF_ATTR_NETWORK_ID, UIP_IP_BUF->proto);
00287 
00288   /* assign values to the channel attribute (port or type + code) */
00289   if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
00290     c = UIP_UDP_BUF->srcport;
00291     if(UIP_UDP_BUF->destport < c) {
00292       c = UIP_UDP_BUF->destport;
00293     }
00294   } else if(UIP_IP_BUF->proto == UIP_PROTO_TCP) {
00295     c = UIP_TCP_BUF->srcport;
00296     if(UIP_TCP_BUF->destport < c) {
00297       c = UIP_TCP_BUF->destport;
00298     }
00299   } else if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6) {
00300     c = UIP_ICMP_BUF->type << 8 | UIP_ICMP_BUF->icode;
00301   }
00302 
00303   packetbuf_set_attr(PACKETBUF_ATTR_CHANNEL, c);
00304 
00305 /*   if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) { */
00306 /*     own = 1; */
00307 /*   } */
00308 
00309 }
00310 
00311 
00312 
00313 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
00314 /** \name HC06 specific variables
00315  *  @{
00316  */
00317 
00318 /** Addresses contexts for IPHC. */
00319 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
00320 static struct sicslowpan_addr_context 
00321 addr_contexts[SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS];
00322 #endif
00323 
00324 /** pointer to an address context. */
00325 static struct sicslowpan_addr_context *context;
00326 
00327 /** pointer to the byte where to write next inline field. */
00328 static uint8_t *hc06_ptr;
00329 
00330 /* Uncompression of linklocal */
00331 /*   0 -> 16 bytes from packet  */
00332 /*   1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet */
00333 /*   2 -> 2 bytes from prefix - 0000::00ff:fe00:XXXX from packet */
00334 /*   3 -> 2 bytes from prefix - infer 8 bytes from lladdr */
00335 /*   NOTE: => the uncompress function does change 0xf to 0x10 */
00336 /*   NOTE: 0x00 => no-autoconfig => unspecified */
00337 const uint8_t unc_llconf[] = {0x0f,0x28,0x22,0x20};
00338 
00339 /* Uncompression of ctx-based */
00340 /*   0 -> 0 bits from packet [unspecified / reserved] */
00341 /*   1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet */
00342 /*   2 -> 8 bytes from prefix - 0000::00ff:fe00:XXXX + 2 from packet */
00343 /*   3 -> 8 bytes from prefix - infer 8 bytes from lladdr */
00344 const uint8_t unc_ctxconf[] = {0x00,0x88,0x82,0x80};
00345 
00346 /* Uncompression of ctx-based */
00347 /*   0 -> 0 bits from packet  */
00348 /*   1 -> 2 bytes from prefix - bunch of zeroes 5 from packet */
00349 /*   2 -> 2 bytes from prefix - zeroes + 3 from packet */
00350 /*   3 -> 2 bytes from prefix - infer 1 bytes from lladdr */
00351 const uint8_t unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
00352 
00353 /* Link local prefix */
00354 const uint8_t llprefix[] = {0xfe, 0x80};
00355 
00356 /* TTL uncompression values */
00357 static const uint8_t ttl_values[] = {0, 1, 64, 255};
00358 
00359 /*--------------------------------------------------------------------*/
00360 /** \name HC06 related functions
00361  * @{                                                                 */
00362 /*--------------------------------------------------------------------*/
00363 /** \brief find the context corresponding to prefix ipaddr */
00364 static struct sicslowpan_addr_context*
00365 addr_context_lookup_by_prefix(uip_ipaddr_t *ipaddr)
00366 {
00367 /* Remove code to avoid warnings and save flash if no context is used */
00368 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
00369   int i;
00370   for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
00371     if((addr_contexts[i].used == 1) &&
00372        uip_ipaddr_prefixcmp(&addr_contexts[i].prefix, ipaddr, 64)) {
00373       return &addr_contexts[i];
00374     }
00375   }
00376 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
00377   return NULL;
00378 }
00379 /*--------------------------------------------------------------------*/
00380 /** \brief find the context with the given number */
00381 static struct sicslowpan_addr_context*
00382 addr_context_lookup_by_number(uint8_t number)
00383 {
00384 /* Remove code to avoid warnings and save flash if no context is used */ 
00385 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0
00386   int i;
00387   for(i = 0; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
00388     if((addr_contexts[i].used == 1) &&
00389        addr_contexts[i].number == number) {
00390       return &addr_contexts[i];
00391     }
00392   }
00393 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
00394   return NULL;
00395 }
00396 /*--------------------------------------------------------------------*/
00397 static uint8_t
00398 compress_addr_64(uint8_t bitpos, uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
00399 {
00400   if(uip_is_addr_mac_addr_based(ipaddr, lladdr)) {
00401     return 3 << bitpos; /* 0-bits */
00402   } else if(sicslowpan_is_iid_16_bit_compressable(ipaddr)) {
00403     /* compress IID to 16 bits xxxx::0000:00ff:fe00:XXXX */
00404     memcpy(hc06_ptr, &ipaddr->u16[7], 2);
00405     hc06_ptr += 2;
00406     return 2 << bitpos; /* 16-bits */
00407   } else {
00408     /* do not compress IID => xxxx::IID */
00409     memcpy(hc06_ptr, &ipaddr->u16[4], 8);
00410     hc06_ptr += 8;
00411     return 1 << bitpos; /* 64-bits */
00412   }
00413 }
00414 
00415 /*-------------------------------------------------------------------- */
00416 /* Uncompress addresses based on a prefix and a postfix with zeroes in
00417  * between. If the postfix is zero in length it will use the link address
00418  * to configure the IP address (autoconf style).
00419  * pref_post_count takes a byte where the first nibble specify prefix count
00420  * and the second postfix count (NOTE: 15/0xf => 16 bytes copy).
00421  */
00422 static void
00423 uncompress_addr(uip_ipaddr_t *ipaddr, uint8_t const prefix[],
00424                 uint8_t pref_post_count, uip_lladdr_t *lladdr)
00425 {
00426   uint8_t prefcount = pref_post_count >> 4;
00427   uint8_t postcount = pref_post_count & 0x0f;
00428   /* full nibble 15 => 16 */
00429   prefcount = prefcount == 15 ? 16 : prefcount;
00430   postcount = postcount == 15 ? 16 : postcount;
00431 
00432   PRINTF("Uncompressing %d + %d => ", prefcount, postcount);
00433 
00434   if(prefcount > 0) {
00435     memcpy(ipaddr, prefix, prefcount);
00436   }
00437   if(prefcount + postcount < 16) {
00438     memset(&ipaddr->u8[prefcount], 0, 16 - (prefcount + postcount));
00439   }
00440   if(postcount > 0) {
00441     memcpy(&ipaddr->u8[16 - postcount], hc06_ptr, postcount);
00442     if(postcount == 2 && prefcount < 11) {
00443       /* 16 bits uncompression => 0000:00ff:fe00:XXXX */
00444       ipaddr->u8[11] = 0xff;
00445       ipaddr->u8[12] = 0xfe;
00446     }
00447     hc06_ptr += postcount;
00448   } else if (prefcount > 0) {
00449     /* no IID based configuration if no prefix and no data => unspec */
00450     uip_ds6_set_addr_iid(ipaddr, lladdr);
00451   }
00452 
00453   PRINT6ADDR(ipaddr);
00454   PRINTF("\n");
00455 }
00456 
00457 /*--------------------------------------------------------------------*/
00458 /**
00459  * \brief Compress IP/UDP header
00460  *
00461  * This function is called by the 6lowpan code to create a compressed
00462  * 6lowpan packet in the packetbuf buffer from a full IPv6 packet in the
00463  * uip_buf buffer.
00464  *
00465  *
00466  * HC-06 (draft-ietf-6lowpan-hc, version 6)\n
00467  * http://tools.ietf.org/html/draft-ietf-6lowpan-hc-06
00468  *
00469  * \note We do not support ISA100_UDP header compression
00470  *
00471  * For LOWPAN_UDP compression, we either compress both ports or none.
00472  * General format with LOWPAN_UDP compression is
00473  * \verbatim
00474  *                      1                   2                   3
00475  *  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
00476  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00477  * |0|1|1|TF |N|HLI|C|S|SAM|M|D|DAM| SCI   | DCI   | comp. IPv6 hdr|
00478  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00479  * | compressed IPv6 fields .....                                  |
00480  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00481  * | LOWPAN_UDP    | non compressed UDP fields ...                 |
00482  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00483  * | L4 data ...                                                   |
00484  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00485  * \endverbatim
00486  * \note The context number 00 is reserved for the link local prefix.
00487  * For unicast addresses, if we cannot compress the prefix, we neither
00488  * compress the IID.
00489  * \param rime_destaddr L2 destination address, needed to compress IP
00490  * dest
00491  */
00492 static void
00493 compress_hdr_hc06(rimeaddr_t *rime_destaddr)
00494 {
00495   uint8_t tmp, iphc0, iphc1;
00496 #if DEBUG
00497   { uint16_t ndx;
00498     PRINTF("before compression (%d): ", UIP_IP_BUF->len[1]);
00499     for(ndx = 0; ndx < UIP_IP_BUF->len[1] + 40; ndx++) {
00500       uint8_t data = ((uint8_t *) (UIP_IP_BUF))[ndx];
00501       PRINTF("%02x", data);
00502     }
00503     PRINTF("\n");
00504   }
00505 #endif
00506 
00507   hc06_ptr = rime_ptr + 2;
00508   /*
00509    * As we copy some bit-length fields, in the IPHC encoding bytes,
00510    * we sometimes use |=
00511    * If the field is 0, and the current bit value in memory is 1,
00512    * this does not work. We therefore reset the IPHC encoding here
00513    */
00514 
00515   iphc0 = SICSLOWPAN_DISPATCH_IPHC;
00516   iphc1 = 0;
00517   RIME_IPHC_BUF[2] = 0; /* might not be used - but needs to be cleared */
00518 
00519   /*
00520    * Address handling needs to be made first since it might
00521    * cause an extra byte with [ SCI | DCI ]
00522    *
00523    */
00524 
00525 
00526   /* check if dest context exists (for allocating third byte) */
00527   /* TODO: fix this so that it remembers the looked up values for
00528      avoiding two lookups - or set the lookup values immediately */
00529   if(addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr) != NULL ||
00530      addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr) != NULL) {
00531     /* set context flag and increase hc06_ptr */
00532     PRINTF("IPHC: compressing dest or src ipaddr - setting CID\n");
00533     iphc1 |= SICSLOWPAN_IPHC_CID;
00534     hc06_ptr++;
00535   }
00536 
00537   /*
00538    * Traffic class, flow label
00539    * If flow label is 0, compress it. If traffic class is 0, compress it
00540    * We have to process both in the same time as the offset of traffic class
00541    * depends on the presence of version and flow label
00542    */
00543  
00544   /* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */
00545   tmp = (UIP_IP_BUF->vtc << 4) | (UIP_IP_BUF->tcflow >> 4);
00546   tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
00547   
00548   if(((UIP_IP_BUF->tcflow & 0x0F) == 0) &&
00549      (UIP_IP_BUF->flow == 0)) {
00550     /* flow label can be compressed */
00551     iphc0 |= SICSLOWPAN_IPHC_FL_C;
00552     if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
00553        ((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
00554       /* compress (elide) all */
00555       iphc0 |= SICSLOWPAN_IPHC_TC_C;
00556     } else {
00557       /* compress only the flow label */
00558      *hc06_ptr = tmp;
00559       hc06_ptr += 1;
00560     }
00561   } else {
00562     /* Flow label cannot be compressed */
00563     if(((UIP_IP_BUF->vtc & 0x0F) == 0) &&
00564        ((UIP_IP_BUF->tcflow & 0xF0) == 0)) {
00565       /* compress only traffic class */
00566       iphc0 |= SICSLOWPAN_IPHC_TC_C;
00567       *hc06_ptr = (tmp & 0xc0) |
00568         (UIP_IP_BUF->tcflow & 0x0F);
00569       memcpy(hc06_ptr + 1, &UIP_IP_BUF->flow, 2);
00570       hc06_ptr += 3;
00571     } else {
00572       /* compress nothing */
00573       memcpy(hc06_ptr, &UIP_IP_BUF->vtc, 4);
00574       /* but replace the top byte with the new ECN | DSCP format*/
00575       *hc06_ptr = tmp;
00576       hc06_ptr += 4;
00577    }
00578   }
00579 
00580   /* Note that the payload length is always compressed */
00581 
00582   /* Next header. We compress it if UDP */
00583 #if UIP_CONF_UDP || UIP_CONF_ROUTER
00584   if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
00585     iphc0 |= SICSLOWPAN_IPHC_NH_C;
00586   }
00587 #endif /*UIP_CONF_UDP*/
00588 #ifdef SICSLOWPAN_NH_COMPRESSOR 
00589   if(SICSLOWPAN_NH_COMPRESSOR.is_compressable(UIP_IP_BUF->proto)) {
00590     iphc0 |= SICSLOWPAN_IPHC_NH_C;
00591   }
00592 #endif
00593   if ((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
00594     *hc06_ptr = UIP_IP_BUF->proto;
00595     hc06_ptr += 1;
00596   }
00597 
00598   /*
00599    * Hop limit
00600    * if 1: compress, encoding is 01
00601    * if 64: compress, encoding is 10
00602    * if 255: compress, encoding is 11
00603    * else do not compress
00604    */
00605   switch(UIP_IP_BUF->ttl) {
00606     case 1:
00607       iphc0 |= SICSLOWPAN_IPHC_TTL_1;
00608       break;
00609     case 64:
00610       iphc0 |= SICSLOWPAN_IPHC_TTL_64;
00611       break;
00612     case 255:
00613       iphc0 |= SICSLOWPAN_IPHC_TTL_255;
00614       break;
00615     default:
00616       *hc06_ptr = UIP_IP_BUF->ttl;
00617       hc06_ptr += 1;
00618       break;
00619   }
00620 
00621   /* source address - cannot be multicast */
00622   if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
00623     PRINTF("IPHC: compressing unspecified - setting SAC\n");
00624     iphc1 |= SICSLOWPAN_IPHC_SAC;
00625     iphc1 |= SICSLOWPAN_IPHC_SAM_00;
00626   } else if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->srcipaddr))
00627      != NULL) {
00628     /* elide the prefix - indicate by CID and set context + SAC */
00629     PRINTF("IPHC: compressing src with context - setting CID & SAC ctx: %d\n",
00630            context->number);
00631     iphc1 |= SICSLOWPAN_IPHC_CID | SICSLOWPAN_IPHC_SAC;
00632     RIME_IPHC_BUF[2] |= context->number << 4;
00633     /* compession compare with this nodes address (source) */
00634 
00635     iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
00636                               &UIP_IP_BUF->srcipaddr, &uip_lladdr);
00637     /* No context found for this address */
00638   } else if(uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) &&
00639             UIP_IP_BUF->destipaddr.u16[1] == 0 &&
00640             UIP_IP_BUF->destipaddr.u16[2] == 0 &&
00641             UIP_IP_BUF->destipaddr.u16[3] == 0) {
00642     iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_SAM_BIT,
00643                               &UIP_IP_BUF->srcipaddr, &uip_lladdr);
00644   } else {
00645     /* send the full address => SAC = 0, SAM = 00 */
00646     iphc1 |= SICSLOWPAN_IPHC_SAM_00; /* 128-bits */
00647     memcpy(hc06_ptr, &UIP_IP_BUF->srcipaddr.u16[0], 16);
00648     hc06_ptr += 16;
00649   }
00650 
00651   /* dest address*/
00652   if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
00653     /* Address is multicast, try to compress */
00654     iphc1 |= SICSLOWPAN_IPHC_M;
00655     if(sicslowpan_is_mcast_addr_compressable8(&UIP_IP_BUF->destipaddr)) {
00656       iphc1 |= SICSLOWPAN_IPHC_DAM_11;
00657       /* use last byte */
00658       *hc06_ptr = UIP_IP_BUF->destipaddr.u8[15];
00659       hc06_ptr += 1;
00660     } else if(sicslowpan_is_mcast_addr_compressable32(&UIP_IP_BUF->destipaddr)) {
00661       iphc1 |= SICSLOWPAN_IPHC_DAM_10;
00662       /* second byte + the last three */
00663       *hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
00664       memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[13], 3);
00665       hc06_ptr += 4;
00666     } else if(sicslowpan_is_mcast_addr_compressable48(&UIP_IP_BUF->destipaddr)) {
00667       iphc1 |= SICSLOWPAN_IPHC_DAM_01;
00668       /* second byte + the last five */
00669       *hc06_ptr = UIP_IP_BUF->destipaddr.u8[1];
00670       memcpy(hc06_ptr + 1, &UIP_IP_BUF->destipaddr.u8[11], 5);
00671       hc06_ptr += 6;
00672     } else {
00673       iphc1 |= SICSLOWPAN_IPHC_DAM_00;
00674       /* full address */
00675       memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u8[0], 16);
00676       hc06_ptr += 16;
00677     }
00678   } else {
00679     /* Address is unicast, try to compress */
00680     if((context = addr_context_lookup_by_prefix(&UIP_IP_BUF->destipaddr)) != NULL) {
00681       /* elide the prefix */
00682       iphc1 |= SICSLOWPAN_IPHC_DAC;
00683       RIME_IPHC_BUF[2] |= context->number;
00684       /* compession compare with link adress (destination) */
00685 
00686       iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
00687                &UIP_IP_BUF->destipaddr, (uip_lladdr_t *)rime_destaddr);
00688       /* No context found for this address */
00689     } else if(uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) &&
00690               UIP_IP_BUF->destipaddr.u16[1] == 0 &&
00691               UIP_IP_BUF->destipaddr.u16[2] == 0 &&
00692               UIP_IP_BUF->destipaddr.u16[3] == 0) {
00693       iphc1 |= compress_addr_64(SICSLOWPAN_IPHC_DAM_BIT,
00694                &UIP_IP_BUF->destipaddr, (uip_lladdr_t *)rime_destaddr);
00695     } else {
00696       /* send the full address */
00697       iphc1 |= SICSLOWPAN_IPHC_DAM_00; /* 128-bits */
00698       memcpy(hc06_ptr, &UIP_IP_BUF->destipaddr.u16[0], 16);
00699       hc06_ptr += 16;
00700     }
00701   }
00702 
00703   uncomp_hdr_len = UIP_IPH_LEN;
00704 
00705 #if UIP_CONF_UDP || UIP_CONF_ROUTER
00706   /* UDP header compression */
00707   if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
00708     PRINTF("IPHC: Uncompressed UDP ports on send side: %x, %x\n",
00709            UIP_HTONS(UIP_UDP_BUF->srcport), UIP_HTONS(UIP_UDP_BUF->destport));
00710     /* Mask out the last 4 bits can be used as a mask */
00711     if(((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN) &&
00712        ((UIP_HTONS(UIP_UDP_BUF->destport) & 0xfff0) == SICSLOWPAN_UDP_4_BIT_PORT_MIN)) {
00713       /* we can compress 12 bits of both source and dest */
00714       *hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_11;
00715       PRINTF("IPHC: remove 12 b of both source & dest with prefix 0xFOB\n");
00716       *(hc06_ptr + 1) =
00717         (uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
00718                 SICSLOWPAN_UDP_4_BIT_PORT_MIN) << 4) +
00719         (uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
00720                 SICSLOWPAN_UDP_4_BIT_PORT_MIN));
00721       hc06_ptr += 2;
00722     } else if((UIP_HTONS(UIP_UDP_BUF->destport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
00723       /* we can compress 8 bits of dest, leave source. */
00724       *hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_01;
00725       PRINTF("IPHC: leave source, remove 8 bits of dest with prefix 0xF0\n");
00726       memcpy(hc06_ptr + 1, &UIP_UDP_BUF->srcport, 2);
00727       *(hc06_ptr + 3) =
00728         (uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) -
00729                 SICSLOWPAN_UDP_8_BIT_PORT_MIN));
00730       hc06_ptr += 4;
00731     } else if((UIP_HTONS(UIP_UDP_BUF->srcport) & 0xff00) == SICSLOWPAN_UDP_8_BIT_PORT_MIN) {
00732       /* we can compress 8 bits of src, leave dest. Copy compressed port */
00733       *hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_10;
00734       PRINTF("IPHC: remove 8 bits of source with prefix 0xF0, leave dest. hch: %i\n", *hc06_ptr);
00735       *(hc06_ptr + 1) =
00736         (uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
00737                 SICSLOWPAN_UDP_8_BIT_PORT_MIN));
00738       memcpy(hc06_ptr + 2, &UIP_UDP_BUF->destport, 2);
00739       hc06_ptr += 4;
00740     } else {
00741       /* we cannot compress. Copy uncompressed ports, full checksum  */
00742       *hc06_ptr = SICSLOWPAN_NHC_UDP_CS_P_00;
00743       PRINTF("IPHC: cannot compress headers\n");
00744       memcpy(hc06_ptr + 1, &UIP_UDP_BUF->srcport, 4);
00745       hc06_ptr += 5;
00746     }
00747     /* always inline the checksum  */
00748     if(1) {
00749       memcpy(hc06_ptr, &UIP_UDP_BUF->udpchksum, 2);
00750       hc06_ptr += 2;
00751     }
00752     uncomp_hdr_len += UIP_UDPH_LEN;
00753   }
00754 #endif /*UIP_CONF_UDP*/
00755 
00756 #ifdef SICSLOWPAN_NH_COMPRESSOR
00757   /* if nothing to compress just return zero  */
00758   hc06_ptr += SICSLOWPAN_NH_COMPRESSOR.compress(hc06_ptr, &uncomp_hdr_len);
00759 #endif
00760 
00761   /* before the rime_hdr_len operation */
00762   RIME_IPHC_BUF[0] = iphc0;
00763   RIME_IPHC_BUF[1] = iphc1;
00764 
00765   rime_hdr_len = hc06_ptr - rime_ptr;
00766   return;
00767 }
00768 
00769 /*--------------------------------------------------------------------*/
00770 /**
00771  * \brief Uncompress HC06 (i.e., IPHC and LOWPAN_UDP) headers and put
00772  * them in sicslowpan_buf
00773  *
00774  * This function is called by the input function when the dispatch is
00775  * HC06.
00776  * We %process the packet in the rime buffer, uncompress the header
00777  * fields, and copy the result in the sicslowpan buffer.
00778  * At the end of the decompression, rime_hdr_len and uncompressed_hdr_len
00779  * are set to the appropriate values
00780  *
00781  * \param ip_len Equal to 0 if the packet is not a fragment (IP length
00782  * is then inferred from the L2 length), non 0 if the packet is a 1st
00783  * fragment.
00784  */
00785 static void
00786 uncompress_hdr_hc06(uint16_t ip_len)
00787 {
00788   uint8_t tmp, iphc0, iphc1;
00789   /* at least two byte will be used for the encoding */
00790   hc06_ptr = rime_ptr + rime_hdr_len + 2;
00791 
00792   iphc0 = RIME_IPHC_BUF[0];
00793   iphc1 = RIME_IPHC_BUF[1];
00794 
00795   /* another if the CID flag is set */
00796   if(iphc1 & SICSLOWPAN_IPHC_CID) {
00797     PRINTF("IPHC: CID flag set - increase header with one\n");
00798     hc06_ptr++;
00799   }
00800 
00801   /* Traffic class and flow label */
00802     if((iphc0 & SICSLOWPAN_IPHC_FL_C) == 0) {
00803       /* Flow label are carried inline */
00804       if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
00805         /* Traffic class is carried inline */
00806         memcpy(&SICSLOWPAN_IP_BUF->tcflow, hc06_ptr + 1, 3);
00807         tmp = *hc06_ptr;
00808         hc06_ptr += 4;
00809         /* hc06 format of tc is ECN | DSCP , original is DSCP | ECN */
00810         /* set version, pick highest DSCP bits and set in vtc */
00811         SICSLOWPAN_IP_BUF->vtc = 0x60 | ((tmp >> 2) & 0x0f);
00812         /* ECN rolled down two steps + lowest DSCP bits at top two bits */
00813         SICSLOWPAN_IP_BUF->tcflow = ((tmp >> 2) & 0x30) | (tmp << 6) |
00814         (SICSLOWPAN_IP_BUF->tcflow & 0x0f);
00815       } else {
00816         /* Traffic class is compressed (set version and no TC)*/
00817         SICSLOWPAN_IP_BUF->vtc = 0x60;
00818         /* highest flow label bits + ECN bits */
00819         SICSLOWPAN_IP_BUF->tcflow = (*hc06_ptr & 0x0F) |
00820         ((*hc06_ptr >> 2) & 0x30);
00821         memcpy(&SICSLOWPAN_IP_BUF->flow, hc06_ptr + 1, 2);
00822         hc06_ptr += 3;
00823       }
00824     } else {
00825       /* Version is always 6! */
00826       /* Version and flow label are compressed */
00827       if((iphc0 & SICSLOWPAN_IPHC_TC_C) == 0) {
00828         /* Traffic class is inline */
00829           SICSLOWPAN_IP_BUF->vtc = 0x60 | ((*hc06_ptr >> 2) & 0x0f);
00830           SICSLOWPAN_IP_BUF->tcflow = ((*hc06_ptr << 6) & 0xC0) | ((*hc06_ptr >> 2) & 0x30);
00831           SICSLOWPAN_IP_BUF->flow = 0;
00832           hc06_ptr += 1;
00833       } else {
00834         /* Traffic class is compressed */
00835         SICSLOWPAN_IP_BUF->vtc = 0x60;
00836         SICSLOWPAN_IP_BUF->tcflow = 0;
00837         SICSLOWPAN_IP_BUF->flow = 0;
00838       }
00839     }
00840 
00841   /* Next Header */
00842   if((iphc0 & SICSLOWPAN_IPHC_NH_C) == 0) {
00843     /* Next header is carried inline */
00844     SICSLOWPAN_IP_BUF->proto = *hc06_ptr;
00845     PRINTF("IPHC: next header inline: %d\n", SICSLOWPAN_IP_BUF->proto);
00846     hc06_ptr += 1;
00847   }
00848 
00849   /* Hop limit */
00850   if((iphc0 & 0x03) != SICSLOWPAN_IPHC_TTL_I) {
00851     SICSLOWPAN_IP_BUF->ttl = ttl_values[iphc0 & 0x03];
00852   } else {
00853     SICSLOWPAN_IP_BUF->ttl = *hc06_ptr;
00854     hc06_ptr += 1;
00855   }
00856 
00857   /* put the source address compression mode SAM in the tmp var */
00858   tmp = ((iphc1 & SICSLOWPAN_IPHC_SAM_11) >> SICSLOWPAN_IPHC_SAM_BIT) & 0x03;
00859 
00860   /* context based compression */
00861   if(iphc1 & SICSLOWPAN_IPHC_SAC) {
00862     uint8_t sci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
00863       RIME_IPHC_BUF[2] >> 4 : 0;
00864 
00865     /* Source address - check context != NULL only if SAM bits are != 0*/
00866     if (tmp != 0) {
00867       context = addr_context_lookup_by_number(sci);
00868       if(context == NULL) {
00869         PRINTF("sicslowpan uncompress_hdr: error context not found\n");
00870         return;
00871       }
00872     }
00873     /* if tmp == 0 we do not have a context and therefore no prefix */
00874     uncompress_addr(&SICSLOWPAN_IP_BUF->srcipaddr,
00875                     tmp != 0 ? context->prefix : NULL, unc_ctxconf[tmp],
00876                     (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
00877   } else {
00878     /* no compression and link local */
00879     uncompress_addr(&SICSLOWPAN_IP_BUF->srcipaddr, llprefix, unc_llconf[tmp],
00880                     (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
00881   }
00882 
00883   /* Destination address */
00884   /* put the destination address compression mode into tmp */
00885   tmp = ((iphc1 & SICSLOWPAN_IPHC_DAM_11) >> SICSLOWPAN_IPHC_DAM_BIT) & 0x03;
00886 
00887   /* multicast compression */
00888   if(iphc1 & SICSLOWPAN_IPHC_M) {
00889     /* context based multicast compression */
00890     if(iphc1 & SICSLOWPAN_IPHC_DAC) {
00891       /* TODO: implement this */
00892     } else {
00893       /* non-context based multicast compression - */
00894       /* DAM_00: 128 bits  */
00895       /* DAM_01:  48 bits FFXX::00XX:XXXX:XXXX */
00896       /* DAM_10:  32 bits FFXX::00XX:XXXX */
00897       /* DAM_11:   8 bits FF02::00XX */
00898       uint8_t prefix[] = {0xff, 0x02};
00899       if(tmp > 0 && tmp < 3) {
00900         prefix[1] = *hc06_ptr;
00901         hc06_ptr++;
00902       }
00903 
00904       uncompress_addr(&SICSLOWPAN_IP_BUF->destipaddr, prefix,
00905                       unc_mxconf[tmp], NULL);
00906     }
00907   } else {
00908     /* no multicast */
00909     /* Context based */
00910     if(iphc1 & SICSLOWPAN_IPHC_DAC) {
00911       uint8_t dci = (iphc1 & SICSLOWPAN_IPHC_CID) ?
00912         RIME_IPHC_BUF[2] & 0x0f : 0;
00913       context = addr_context_lookup_by_number(dci);
00914 
00915       /* all valid cases below need the context! */
00916       if(context == NULL) {
00917         PRINTF("sicslowpan uncompress_hdr: error context not found\n");
00918         return;
00919       }
00920       uncompress_addr(&SICSLOWPAN_IP_BUF->destipaddr, context->prefix,
00921                       unc_ctxconf[tmp],
00922                       (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00923     } else {
00924       /* not context based => link local M = 0, DAC = 0 - same as SAC */
00925       uncompress_addr(&SICSLOWPAN_IP_BUF->destipaddr, llprefix,
00926                       unc_llconf[tmp],
00927                       (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
00928     }
00929   }
00930   uncomp_hdr_len += UIP_IPH_LEN;
00931 
00932   /* Next header processing - continued */
00933   if((iphc0 & SICSLOWPAN_IPHC_NH_C)) {
00934     /* The next header is compressed, NHC is following */
00935     if((*hc06_ptr & SICSLOWPAN_NHC_UDP_MASK) == SICSLOWPAN_NHC_UDP_ID) {
00936       uint8_t checksum_compressed;
00937       SICSLOWPAN_IP_BUF->proto = UIP_PROTO_UDP;
00938       checksum_compressed = *hc06_ptr & SICSLOWPAN_NHC_UDP_CHECKSUMC;
00939       PRINTF("IPHC: Incoming header value: %i\n", *hc06_ptr);
00940       switch(*hc06_ptr & SICSLOWPAN_NHC_UDP_CS_P_11) {
00941       case SICSLOWPAN_NHC_UDP_CS_P_00:
00942         /* 1 byte for NHC, 4 byte for ports, 2 bytes chksum */
00943         memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
00944         memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 3, 2);
00945         PRINTF("IPHC: Uncompressed UDP ports (ptr+5): %x, %x\n",
00946                UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
00947         hc06_ptr += 5;
00948         break;
00949 
00950       case SICSLOWPAN_NHC_UDP_CS_P_01:
00951         /* 1 byte for NHC + source 16bit inline, dest = 0xF0 + 8 bit inline */
00952         PRINTF("IPHC: Decompressing destination\n");
00953         memcpy(&SICSLOWPAN_UDP_BUF->srcport, hc06_ptr + 1, 2);
00954         SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN + (*(hc06_ptr + 3)));
00955         PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
00956                UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
00957         hc06_ptr += 4;
00958         break;
00959 
00960       case SICSLOWPAN_NHC_UDP_CS_P_10:
00961         /* 1 byte for NHC + source = 0xF0 + 8bit inline, dest = 16 bit inline*/
00962         PRINTF("IPHC: Decompressing source\n");
00963         SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_8_BIT_PORT_MIN +
00964                                             (*(hc06_ptr + 1)));
00965         memcpy(&SICSLOWPAN_UDP_BUF->destport, hc06_ptr + 2, 2);
00966         PRINTF("IPHC: Uncompressed UDP ports (ptr+4): %x, %x\n",
00967                UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
00968         hc06_ptr += 4;
00969         break;
00970 
00971       case SICSLOWPAN_NHC_UDP_CS_P_11:
00972         /* 1 byte for NHC, 1 byte for ports */
00973         SICSLOWPAN_UDP_BUF->srcport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
00974                                             (*(hc06_ptr + 1) >> 4));
00975         SICSLOWPAN_UDP_BUF->destport = UIP_HTONS(SICSLOWPAN_UDP_4_BIT_PORT_MIN +
00976                                              ((*(hc06_ptr + 1)) & 0x0F));
00977         PRINTF("IPHC: Uncompressed UDP ports (ptr+2): %x, %x\n",
00978                UIP_HTONS(SICSLOWPAN_UDP_BUF->srcport), UIP_HTONS(SICSLOWPAN_UDP_BUF->destport));
00979         hc06_ptr += 2;
00980         break;
00981 
00982       default:
00983         PRINTF("sicslowpan uncompress_hdr: error unsupported UDP compression\n");
00984         return;
00985       }
00986       if(!checksum_compressed) { /* has_checksum, default  */
00987         memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, hc06_ptr, 2);
00988         hc06_ptr += 2;
00989         PRINTF("IPHC: sicslowpan uncompress_hdr: checksum included\n");
00990       } else {
00991         PRINTF("IPHC: sicslowpan uncompress_hdr: checksum *NOT* included\n");
00992       }
00993       uncomp_hdr_len += UIP_UDPH_LEN;
00994     }
00995 #ifdef SICSLOWPAN_NH_COMPRESSOR
00996     else {
00997       hc06_ptr += SICSLOWPAN_NH_COMPRESSOR.uncompress(hc06_ptr, sicslowpan_buf, &uncomp_hdr_len);
00998     }
00999 #endif
01000   }
01001 
01002   rime_hdr_len = hc06_ptr - rime_ptr;
01003   
01004   /* IP length field. */
01005   if(ip_len == 0) {
01006     /* This is not a fragmented packet */
01007     SICSLOWPAN_IP_BUF->len[0] = 0;
01008     SICSLOWPAN_IP_BUF->len[1] = packetbuf_datalen() - rime_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
01009   } else {
01010     /* This is a 1st fragment */
01011     SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
01012     SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
01013   }
01014   
01015   /* length field in UDP header */
01016   if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) {
01017     memcpy(&SICSLOWPAN_UDP_BUF->udplen, &SICSLOWPAN_IP_BUF->len[0], 2);
01018   }
01019 
01020   return;
01021 }
01022 /** @} */
01023 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
01024 
01025 
01026 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1
01027 /*--------------------------------------------------------------------*/
01028 /** \name HC1 compression and uncompression functions
01029  *  @{                                                                */
01030 /*--------------------------------------------------------------------*/
01031 /**
01032  * \brief Compress IP/UDP header using HC1 and HC_UDP
01033  *
01034  * This function is called by the 6lowpan code to create a compressed
01035  * 6lowpan packet in the packetbuf buffer from a full IPv6 packet in the
01036  * uip_buf buffer.
01037  *
01038  *
01039  * If we can compress everything, we use HC1 dispatch, if not we use
01040  * IPv6 dispatch.\n
01041  * We can compress everything if:
01042  *   - IP version is
01043  *   - Flow label and traffic class are 0
01044  *   - Both src and dest ip addresses are link local
01045  *   - Both src and dest interface ID are recoverable from lower layer
01046  *     header
01047  *   - Next header is either ICMP, UDP or TCP
01048  * Moreover, if next header is UDP, we try to compress it using HC_UDP.
01049  * This is feasible is both ports are between F0B0 and F0B0 + 15\n\n
01050  *
01051  * Resulting header structure:
01052  * - For ICMP, TCP, non compressed UDP\n
01053  *   HC1 encoding = 11111010 (UDP) 11111110 (TCP) 11111100 (ICMP)\n
01054  * \verbatim
01055  *                      1                   2                   3
01056  * 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
01057  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
01058  * | LoWPAN HC1 Dsp | HC1 encoding  | IPv6 Hop limit| L4 hdr + data|
01059  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
01060  * | ...
01061  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
01062  * \endverbatim
01063  *
01064  * - For compressed UDP
01065  *   HC1 encoding = 11111011, HC_UDP encoding = 11100000\n
01066  * \verbatim
01067  *                      1                   2                   3
01068  * 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
01069  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
01070  * | LoWPAN HC1 Dsp| HC1 encoding  |  HC_UDP encod.| IPv6 Hop limit|
01071  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
01072  * | src p.| dst p.| UDP checksum                  | L4 data...
01073  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
01074  * \endverbatim
01075  *
01076  * \param rime_destaddr L2 destination address, needed to compress the
01077  * IP destination field
01078  */
01079 static void
01080 compress_hdr_hc1(rimeaddr_t *rime_destaddr)
01081 {
01082   /*
01083    * Check if all the assumptions for full compression
01084    * are valid :
01085    */
01086   if(UIP_IP_BUF->vtc != 0x60 ||
01087      UIP_IP_BUF->tcflow != 0 ||
01088      UIP_IP_BUF->flow != 0 ||
01089      !uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) ||
01090      !uip_is_addr_mac_addr_based(&UIP_IP_BUF->srcipaddr, &uip_lladdr) ||
01091      !uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) ||
01092      !uip_is_addr_mac_addr_based(&UIP_IP_BUF->destipaddr,
01093                                  (uip_lladdr_t *)rime_destaddr) ||
01094      (UIP_IP_BUF->proto != UIP_PROTO_ICMP6 &&
01095       UIP_IP_BUF->proto != UIP_PROTO_UDP &&
01096       UIP_IP_BUF->proto != UIP_PROTO_TCP))
01097   {
01098     /*
01099      * IPV6 DISPATCH
01100      * Something cannot be compressed, use IPV6 DISPATCH,
01101      * compress nothing, copy IPv6 header in rime buffer
01102      */
01103     *rime_ptr = SICSLOWPAN_DISPATCH_IPV6;
01104     rime_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
01105     memcpy(rime_ptr + rime_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
01106     rime_hdr_len += UIP_IPH_LEN;
01107     uncomp_hdr_len += UIP_IPH_LEN;
01108   } else {
01109     /*
01110      * HC1 DISPATCH
01111      * maximum compresssion:
01112      * All fields in the IP header but Hop Limit are elided
01113      * If next header is UDP, we compress UDP header using HC2
01114      */
01115     RIME_HC1_PTR[RIME_HC1_DISPATCH] = SICSLOWPAN_DISPATCH_HC1;
01116     uncomp_hdr_len += UIP_IPH_LEN;
01117     switch(UIP_IP_BUF->proto) {
01118       case UIP_PROTO_ICMP6:
01119         /* HC1 encoding and ttl */
01120         RIME_HC1_PTR[RIME_HC1_ENCODING] = 0xFC;
01121         RIME_HC1_PTR[RIME_HC1_TTL] = UIP_IP_BUF->ttl;
01122         rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
01123         break;
01124 #if UIP_CONF_TCP
01125       case UIP_PROTO_TCP:
01126         /* HC1 encoding and ttl */
01127         RIME_HC1_PTR[RIME_HC1_ENCODING] = 0xFE;
01128         RIME_HC1_PTR[RIME_HC1_TTL] = UIP_IP_BUF->ttl;
01129         rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
01130         break;
01131 #endif /* UIP_CONF_TCP */
01132 #if UIP_CONF_UDP
01133       case UIP_PROTO_UDP:
01134         /*
01135          * try to compress UDP header (we do only full compression).
01136          * This is feasible if both src and dest ports are between
01137          * SICSLOWPAN_UDP_PORT_MIN and SICSLOWPAN_UDP_PORT_MIN + 15
01138          */
01139         PRINTF("local/remote port %u/%u\n",UIP_UDP_BUF->srcport,UIP_UDP_BUF->destport);
01140         if(UIP_HTONS(UIP_UDP_BUF->srcport)  >= SICSLOWPAN_UDP_PORT_MIN &&
01141            UIP_HTONS(UIP_UDP_BUF->srcport)  <  SICSLOWPAN_UDP_PORT_MAX &&
01142            UIP_HTONS(UIP_UDP_BUF->destport) >= SICSLOWPAN_UDP_PORT_MIN &&
01143            UIP_HTONS(UIP_UDP_BUF->destport) <  SICSLOWPAN_UDP_PORT_MAX) {
01144           /* HC1 encoding */
01145           RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_HC1_ENCODING] = 0xFB;
01146         
01147           /* HC_UDP encoding, ttl, src and dest ports, checksum */
01148           RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_UDP_ENCODING] = 0xE0;
01149           RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_TTL] = UIP_IP_BUF->ttl;
01150 
01151           RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_PORTS] =
01152                (uint8_t)((UIP_HTONS(UIP_UDP_BUF->srcport) -
01153                        SICSLOWPAN_UDP_PORT_MIN) << 4) +
01154                (uint8_t)((UIP_HTONS(UIP_UDP_BUF->destport) - SICSLOWPAN_UDP_PORT_MIN));
01155           memcpy(&RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_CHKSUM], &UIP_UDP_BUF->udpchksum, 2);
01156           rime_hdr_len += SICSLOWPAN_HC1_HC_UDP_HDR_LEN;
01157           uncomp_hdr_len += UIP_UDPH_LEN;
01158         } else {
01159           /* HC1 encoding and ttl */
01160           RIME_HC1_PTR[RIME_HC1_ENCODING] = 0xFA;
01161           RIME_HC1_PTR[RIME_HC1_TTL] = UIP_IP_BUF->ttl;
01162           rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
01163         }
01164         break;
01165 #endif /*UIP_CONF_UDP*/
01166     }
01167   }
01168   return;
01169 }
01170 
01171 /*--------------------------------------------------------------------*/
01172 /**
01173  * \brief Uncompress HC1 (and HC_UDP) headers and put them in
01174  * sicslowpan_buf
01175  *
01176  * This function is called by the input function when the dispatch is
01177  * HC1.
01178  * We %process the packet in the rime buffer, uncompress the header
01179  * fields, and copy the result in the sicslowpan buffer.
01180  * At the end of the decompression, rime_hdr_len and uncompressed_hdr_len
01181  * are set to the appropriate values
01182  *
01183  * \param ip_len Equal to 0 if the packet is not a fragment (IP length
01184  * is then inferred from the L2 length), non 0 if the packet is a 1st
01185  * fragment.
01186  */
01187 static void
01188 uncompress_hdr_hc1(uint16_t ip_len)
01189 {
01190   /* version, traffic class, flow label */
01191   SICSLOWPAN_IP_BUF->vtc = 0x60;
01192   SICSLOWPAN_IP_BUF->tcflow = 0;
01193   SICSLOWPAN_IP_BUF->flow = 0;
01194   
01195   /* src and dest ip addresses */
01196   uip_ip6addr(&SICSLOWPAN_IP_BUF->srcipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
01197   uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->srcipaddr,
01198                        (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
01199   uip_ip6addr(&SICSLOWPAN_IP_BUF->destipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
01200   uip_ds6_set_addr_iid(&SICSLOWPAN_IP_BUF->destipaddr,
01201                        (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
01202   
01203   uncomp_hdr_len += UIP_IPH_LEN;
01204   
01205   /* Next header field */
01206   switch(RIME_HC1_PTR[RIME_HC1_ENCODING] & 0x06) {
01207     case SICSLOWPAN_HC1_NH_ICMP6:
01208       SICSLOWPAN_IP_BUF->proto = UIP_PROTO_ICMP6;
01209       SICSLOWPAN_IP_BUF->ttl = RIME_HC1_PTR[RIME_HC1_TTL];
01210       rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
01211       break;
01212 #if UIP_CONF_TCP
01213     case SICSLOWPAN_HC1_NH_TCP:
01214       SICSLOWPAN_IP_BUF->proto = UIP_PROTO_TCP;
01215       SICSLOWPAN_IP_BUF->ttl = RIME_HC1_PTR[RIME_HC1_TTL];
01216       rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
01217       break;
01218 #endif/* UIP_CONF_TCP */
01219 #if UIP_CONF_UDP
01220     case SICSLOWPAN_HC1_NH_UDP:
01221       SICSLOWPAN_IP_BUF->proto = UIP_PROTO_UDP;
01222       if(RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_HC1_ENCODING] & 0x01) {
01223         /* UDP header is compressed with HC_UDP */
01224         if(RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_UDP_ENCODING] !=
01225            SICSLOWPAN_HC_UDP_ALL_C) {
01226           PRINTF("sicslowpan (uncompress_hdr), packet not supported");
01227           return;
01228         }
01229         /* IP TTL */
01230         SICSLOWPAN_IP_BUF->ttl = RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_TTL];
01231         /* UDP ports, len, checksum */
01232         SICSLOWPAN_UDP_BUF->srcport =
01233           UIP_HTONS(SICSLOWPAN_UDP_PORT_MIN +
01234                 (RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_PORTS] >> 4));
01235         SICSLOWPAN_UDP_BUF->destport =
01236           UIP_HTONS(SICSLOWPAN_UDP_PORT_MIN +
01237                 (RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_PORTS] & 0x0F));
01238         memcpy(&SICSLOWPAN_UDP_BUF->udpchksum, &RIME_HC1_HC_UDP_PTR[RIME_HC1_HC_UDP_CHKSUM], 2);
01239         uncomp_hdr_len += UIP_UDPH_LEN;
01240         rime_hdr_len += SICSLOWPAN_HC1_HC_UDP_HDR_LEN;
01241       } else {
01242         rime_hdr_len += SICSLOWPAN_HC1_HDR_LEN;
01243       }
01244       break;
01245 #endif/* UIP_CONF_UDP */
01246     default:
01247       /* this shouldn't happen, drop */
01248       return;
01249   }
01250   
01251   /* IP length field. */
01252   if(ip_len == 0) {
01253     /* This is not a fragmented packet */
01254     SICSLOWPAN_IP_BUF->len[0] = 0;
01255     SICSLOWPAN_IP_BUF->len[1] = packetbuf_datalen() - rime_hdr_len + uncomp_hdr_len - UIP_IPH_LEN;
01256   } else {
01257     /* This is a 1st fragment */
01258     SICSLOWPAN_IP_BUF->len[0] = (ip_len - UIP_IPH_LEN) >> 8;
01259     SICSLOWPAN_IP_BUF->len[1] = (ip_len - UIP_IPH_LEN) & 0x00FF;
01260   }
01261   /* length field in UDP header */
01262   if(SICSLOWPAN_IP_BUF->proto == UIP_PROTO_UDP) {
01263     memcpy(&SICSLOWPAN_UDP_BUF->udplen, &SICSLOWPAN_IP_BUF->len[0], 2);
01264   }
01265   return;
01266 }
01267 /** @} */
01268 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1 */
01269 
01270 
01271 
01272 /*--------------------------------------------------------------------*/
01273 /** \name IPv6 dispatch "compression" function
01274  * @{                                                                 */
01275 /*--------------------------------------------------------------------*/
01276 /* \brief Packets "Compression" when only IPv6 dispatch is used
01277  *
01278  * There is no compression in this case, all fields are sent
01279  * inline. We just add the IPv6 dispatch byte before the packet.
01280  * \verbatim
01281  * 0               1                   2                   3
01282  * 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
01283  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
01284  * | IPv6 Dsp      | IPv6 header and payload ...
01285  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
01286  * \endverbatim
01287  */
01288 static void
01289 compress_hdr_ipv6(rimeaddr_t *rime_destaddr)
01290 {
01291   *rime_ptr = SICSLOWPAN_DISPATCH_IPV6;
01292   rime_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
01293   memcpy(rime_ptr + rime_hdr_len, UIP_IP_BUF, UIP_IPH_LEN);
01294   rime_hdr_len += UIP_IPH_LEN;
01295   uncomp_hdr_len += UIP_IPH_LEN;
01296   return;
01297 }
01298 /** @} */
01299 
01300 /*--------------------------------------------------------------------*/
01301 /** \name Input/output functions common to all compression schemes
01302  * @{                                                                 */
01303 /*--------------------------------------------------------------------*/
01304 /**
01305  * Callback function for the MAC packet sent callback
01306  */
01307 static void
01308 packet_sent(void *ptr, int status, int transmissions)
01309 {
01310 #if SICSLOWPAN_CONF_NEIGHBOR_INFO
01311   neighbor_info_packet_sent(status, transmissions);
01312 #endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */
01313   if(callback != NULL) {
01314     callback->output_callback(status);
01315   }
01316   last_tx_status = status;
01317 }
01318 /*--------------------------------------------------------------------*/
01319 /**
01320  * \brief This function is called by the 6lowpan code to send out a
01321  * packet.
01322  * \param dest the link layer destination address of the packet
01323  */
01324 static void
01325 send_packet(rimeaddr_t *dest)
01326 {
01327   /* Set the link layer destination address for the packet as a
01328    * packetbuf attribute. The MAC layer can access the destination
01329    * address with the function packetbuf_addr(PACKETBUF_ADDR_RECEIVER).
01330    */
01331   packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest);
01332 
01333   /* Force acknowledge from sender (test hardware autoacks) */
01334 #if SICSLOWPAN_CONF_ACK_ALL
01335     packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
01336 #endif
01337 
01338   /* Provide a callback function to receive the result of
01339      a packet transmission. */
01340   NETSTACK_MAC.send(&packet_sent, NULL);
01341 
01342   /* If we are sending multiple packets in a row, we need to let the
01343      watchdog know that we are still alive. */
01344   watchdog_periodic();
01345 }
01346 /*--------------------------------------------------------------------*/
01347 /** \brief Take an IP packet and format it to be sent on an 802.15.4
01348  *  network using 6lowpan.
01349  *  \param localdest The MAC address of the destination
01350  *
01351  *  The IP packet is initially in uip_buf. Its header is compressed
01352  *  and if necessary it is fragmented. The resulting
01353  *  packet/fragments are put in packetbuf and delivered to the 802.15.4
01354  *  MAC.
01355  */
01356 static uint8_t
01357 output(uip_lladdr_t *localdest)
01358 {
01359   /* The MAC address of the destination of the packet */
01360   rimeaddr_t dest;
01361 
01362   /* Number of bytes processed. */
01363   uint16_t processed_ip_out_len;
01364 
01365   /* init */
01366   uncomp_hdr_len = 0;
01367   rime_hdr_len = 0;
01368 
01369   /* reset rime buffer */
01370   packetbuf_clear();
01371   rime_ptr = packetbuf_dataptr();
01372 
01373   packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS,
01374                      SICSLOWPAN_MAX_MAC_TRANSMISSIONS);
01375 
01376   if(callback) {
01377     /* call the attribution when the callback comes, but set attributes
01378        here ! */
01379     set_packet_attrs();
01380   }
01381 
01382 #define TCP_FIN 0x01
01383 #define TCP_ACK 0x10
01384 #define TCP_CTL 0x3f
01385   /* Set stream mode for all TCP packets, except FIN packets. */
01386   if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
01387      (UIP_TCP_BUF->flags & TCP_FIN) == 0 &&
01388      (UIP_TCP_BUF->flags & TCP_CTL) != TCP_ACK) {
01389     packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
01390                        PACKETBUF_ATTR_PACKET_TYPE_STREAM);
01391   } else if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
01392             (UIP_TCP_BUF->flags & TCP_FIN) == TCP_FIN) {
01393     packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE,
01394                        PACKETBUF_ATTR_PACKET_TYPE_STREAM_END);
01395   }
01396 
01397   /*
01398    * The destination address will be tagged to each outbound
01399    * packet. If the argument localdest is NULL, we are sending a
01400    * broadcast packet.
01401    */
01402   if(localdest == NULL) {
01403     rimeaddr_copy(&dest, &rimeaddr_null);
01404   } else {
01405     rimeaddr_copy(&dest, (const rimeaddr_t *)localdest);
01406   }
01407   
01408   PRINTFO("sicslowpan output: sending packet len %d\n", uip_len);
01409 
01410   if(uip_len >= COMPRESSION_THRESHOLD) {
01411     /* Try to compress the headers */
01412 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1
01413     compress_hdr_hc1(&dest);
01414 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1 */
01415 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
01416     compress_hdr_ipv6(&dest);
01417 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6 */
01418 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
01419     compress_hdr_hc06(&dest);
01420 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
01421   } else {
01422     compress_hdr_ipv6(&dest);
01423   }
01424   PRINTFO("sicslowpan output: header of len %d\n", rime_hdr_len);
01425 
01426   if(uip_len - uncomp_hdr_len > MAC_MAX_PAYLOAD - rime_hdr_len) {
01427 #if SICSLOWPAN_CONF_FRAG
01428     struct queuebuf *q;
01429     /*
01430      * The outbound IPv6 packet is too large to fit into a single 15.4
01431      * packet, so we fragment it into multiple packets and send them.
01432      * The first fragment contains frag1 dispatch, then
01433      * IPv6/HC1/HC06/HC_UDP dispatchs/headers.
01434      * The following fragments contain only the fragn dispatch.
01435      */
01436 
01437     PRINTFO("Fragmentation sending packet len %d\n", uip_len);
01438     
01439     /* Create 1st Fragment */
01440     PRINTFO("sicslowpan output: 1rst fragment ");
01441 
01442     /* move HC1/HC06/IPv6 header */
01443     memmove(rime_ptr + SICSLOWPAN_FRAG1_HDR_LEN, rime_ptr, rime_hdr_len);
01444 
01445     /*
01446      * FRAG1 dispatch + header
01447      * Note that the length is in units of 8 bytes
01448      */
01449 /*     RIME_FRAG_BUF->dispatch_size = */
01450 /*       uip_htons((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len); */
01451     SET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE,
01452           ((SICSLOWPAN_DISPATCH_FRAG1 << 8) | uip_len));
01453 /*     RIME_FRAG_BUF->tag = uip_htons(my_tag); */
01454     SET16(RIME_FRAG_PTR, RIME_FRAG_TAG, my_tag);
01455     my_tag++;
01456 
01457     /* Copy payload and send */
01458     rime_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
01459     rime_payload_len = (MAC_MAX_PAYLOAD - rime_hdr_len) & 0xf8;
01460     PRINTFO("(len %d, tag %d)\n", rime_payload_len, my_tag);
01461     memcpy(rime_ptr + rime_hdr_len,
01462            (uint8_t *)UIP_IP_BUF + uncomp_hdr_len, rime_payload_len);
01463     packetbuf_set_datalen(rime_payload_len + rime_hdr_len);
01464     q = queuebuf_new_from_packetbuf();
01465     if(q == NULL) {
01466       PRINTFO("could not allocate queuebuf for first fragment, dropping packet\n");
01467       return 0;
01468     }
01469     send_packet(&dest);
01470     queuebuf_to_packetbuf(q);
01471     queuebuf_free(q);
01472     q = NULL;
01473 
01474     /* Check tx result. */
01475     if((last_tx_status == MAC_TX_COLLISION) ||
01476        (last_tx_status == MAC_TX_ERR) ||
01477        (last_tx_status == MAC_TX_ERR_FATAL)) {
01478       PRINTFO("error in fragment tx, dropping subsequent fragments.\n");
01479       return 0;
01480     }
01481 
01482     /* set processed_ip_out_len to what we already sent from the IP payload*/
01483     processed_ip_out_len = rime_payload_len + uncomp_hdr_len;
01484     
01485     /*
01486      * Create following fragments
01487      * Datagram tag is already in the buffer, we need to set the
01488      * FRAGN dispatch and for each fragment, the offset
01489      */
01490     rime_hdr_len = SICSLOWPAN_FRAGN_HDR_LEN;
01491 /*     RIME_FRAG_BUF->dispatch_size = */
01492 /*       uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */
01493     SET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE,
01494           ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len));
01495     rime_payload_len = (MAC_MAX_PAYLOAD - rime_hdr_len) & 0xf8;
01496     while(processed_ip_out_len < uip_len) {
01497       PRINTFO("sicslowpan output: fragment ");
01498       RIME_FRAG_PTR[RIME_FRAG_OFFSET] = processed_ip_out_len >> 3;
01499       
01500       /* Copy payload and send */
01501       if(uip_len - processed_ip_out_len < rime_payload_len) {
01502         /* last fragment */
01503         rime_payload_len = uip_len - processed_ip_out_len;
01504       }
01505       PRINTFO("(offset %d, len %d, tag %d)\n",
01506              processed_ip_out_len >> 3, rime_payload_len, my_tag);
01507       memcpy(rime_ptr + rime_hdr_len,
01508              (uint8_t *)UIP_IP_BUF + processed_ip_out_len, rime_payload_len);
01509       packetbuf_set_datalen(rime_payload_len + rime_hdr_len);
01510       q = queuebuf_new_from_packetbuf();
01511       if(q == NULL) {
01512         PRINTFO("could not allocate queuebuf, dropping fragment\n");
01513         return 0;
01514       }
01515       send_packet(&dest);
01516       queuebuf_to_packetbuf(q);
01517       queuebuf_free(q);
01518       q = NULL;
01519       processed_ip_out_len += rime_payload_len;
01520 
01521       /* Check tx result. */
01522       if((last_tx_status == MAC_TX_COLLISION) ||
01523          (last_tx_status == MAC_TX_ERR) ||
01524          (last_tx_status == MAC_TX_ERR_FATAL)) {
01525         PRINTFO("error in fragment tx, dropping subsequent fragments.\n");
01526         return 0;
01527       }
01528     }
01529 #else /* SICSLOWPAN_CONF_FRAG */
01530     PRINTFO("sicslowpan output: Packet too large to be sent without fragmentation support; dropping packet\n");
01531     return 0;
01532 #endif /* SICSLOWPAN_CONF_FRAG */
01533   } else {
01534     /*
01535      * The packet does not need to be fragmented
01536      * copy "payload" and send
01537      */
01538     memcpy(rime_ptr + rime_hdr_len, (uint8_t *)UIP_IP_BUF + uncomp_hdr_len,
01539            uip_len - uncomp_hdr_len);
01540     packetbuf_set_datalen(uip_len - uncomp_hdr_len + rime_hdr_len);
01541     send_packet(&dest);
01542   }
01543   return 1;
01544 }
01545 
01546 /*--------------------------------------------------------------------*/
01547 /** \brief Process a received 6lowpan packet.
01548  *  \param r The MAC layer
01549  *
01550  *  The 6lowpan packet is put in packetbuf by the MAC. If its a frag1 or
01551  *  a non-fragmented packet we first uncompress the IP header. The
01552  *  6lowpan payload and possibly the uncompressed IP header are then
01553  *  copied in siclowpan_buf. If the IP packet is complete it is copied
01554  *  to uip_buf and the IP layer is called.
01555  *
01556  * \note We do not check for overlapping sicslowpan fragments
01557  * (it is a SHALL in the RFC 4944 and should never happen)
01558  */
01559 static void
01560 input(void)
01561 {
01562   /* size of the IP packet (read from fragment) */
01563   uint16_t frag_size = 0;
01564   /* offset of the fragment in the IP packet */
01565   uint8_t frag_offset = 0;
01566 #if SICSLOWPAN_CONF_FRAG
01567   /* tag of the fragment */
01568   uint16_t frag_tag = 0;
01569   uint8_t first_fragment = 0, last_fragment = 0;
01570 #endif /*SICSLOWPAN_CONF_FRAG*/
01571 
01572   /* init */
01573   uncomp_hdr_len = 0;
01574   rime_hdr_len = 0;
01575 
01576   /* The MAC puts the 15.4 payload inside the RIME data buffer */
01577   rime_ptr = packetbuf_dataptr();
01578 
01579 #if SICSLOWPAN_CONF_FRAG
01580   /* if reassembly timed out, cancel it */
01581   if(timer_expired(&reass_timer)) {
01582     sicslowpan_len = 0;
01583     processed_ip_in_len = 0;
01584   }
01585   /*
01586    * Since we don't support the mesh and broadcast header, the first header
01587    * we look for is the fragmentation header
01588    */
01589   switch((GET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE) & 0xf800) >> 8) {
01590     case SICSLOWPAN_DISPATCH_FRAG1:
01591       PRINTFI("sicslowpan input: FRAG1 ");
01592       frag_offset = 0;
01593 /*       frag_size = (uip_ntohs(RIME_FRAG_BUF->dispatch_size) & 0x07ff); */
01594       frag_size = GET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
01595 /*       frag_tag = uip_ntohs(RIME_FRAG_BUF->tag); */
01596       frag_tag = GET16(RIME_FRAG_PTR, RIME_FRAG_TAG);
01597       PRINTFI("size %d, tag %d, offset %d)\n",
01598              frag_size, frag_tag, frag_offset);
01599       rime_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN;
01600       /*      printf("frag1 %d %d\n", reass_tag, frag_tag);*/
01601       first_fragment = 1;
01602       break;
01603     case SICSLOWPAN_DISPATCH_FRAGN:
01604       /*
01605        * set offset, tag, size
01606        * Offset is in units of 8 bytes
01607        */
01608       PRINTFI("sicslowpan input: FRAGN ");
01609       frag_offset = RIME_FRAG_PTR[RIME_FRAG_OFFSET];
01610       frag_tag = GET16(RIME_FRAG_PTR, RIME_FRAG_TAG);
01611       frag_size = GET16(RIME_FRAG_PTR, RIME_FRAG_DISPATCH_SIZE) & 0x07ff;
01612       PRINTFI("size %d, tag %d, offset %d)\n",
01613              frag_size, frag_tag, frag_offset);
01614       rime_hdr_len += SICSLOWPAN_FRAGN_HDR_LEN;
01615 
01616       /* If this is the last fragment, we may shave off any extrenous
01617          bytes at the end. We must be liberal in what we accept. */
01618       PRINTFI("last_fragment?: processed_ip_in_len %d rime_payload_len %d frag_size %d\n",
01619               processed_ip_in_len, packetbuf_datalen() - rime_hdr_len, frag_size);
01620 
01621       if(processed_ip_in_len + packetbuf_datalen() - rime_hdr_len >= frag_size) {
01622         last_fragment = 1;
01623       }
01624       break;
01625     default:
01626       break;
01627   }
01628 
01629   if(processed_ip_in_len > 0) {
01630     /* reassembly is ongoing */
01631     /*    printf("frag %d %d\n", reass_tag, frag_tag);*/
01632     if((frag_size > 0 &&
01633         (frag_size != sicslowpan_len ||
01634          reass_tag  != frag_tag ||
01635          !rimeaddr_cmp(&frag_sender, packetbuf_addr(PACKETBUF_ADDR_SENDER))))  ||
01636        frag_size == 0) {
01637       /*
01638        * the packet is a fragment that does not belong to the packet
01639        * being reassembled or the packet is not a fragment.
01640        */
01641       PRINTFI("sicslowpan input: Dropping 6lowpan packet that is not a fragment of the packet currently being reassembled\n");
01642       return;
01643     }
01644   } else {
01645     /*
01646      * reassembly is off
01647      * start it if we received a fragment
01648      */
01649     if((frag_size > 0) && (frag_size <= UIP_BUFSIZE)) {
01650       sicslowpan_len = frag_size;
01651       reass_tag = frag_tag;
01652       timer_set(&reass_timer, SICSLOWPAN_REASS_MAXAGE*CLOCK_SECOND);
01653       PRINTFI("sicslowpan input: INIT FRAGMENTATION (len %d, tag %d)\n",
01654              sicslowpan_len, reass_tag);
01655       rimeaddr_copy(&frag_sender, packetbuf_addr(PACKETBUF_ADDR_SENDER));
01656     }
01657   }
01658 
01659   if(rime_hdr_len == SICSLOWPAN_FRAGN_HDR_LEN) {
01660     /* this is a FRAGN, skip the header compression dispatch section */
01661     goto copypayload;
01662   }
01663 #endif /* SICSLOWPAN_CONF_FRAG */
01664 
01665   /* Process next dispatch and headers */
01666 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
01667   if((RIME_HC1_PTR[RIME_HC1_DISPATCH] & 0xe0) == SICSLOWPAN_DISPATCH_IPHC) {
01668     PRINTFI("sicslowpan input: IPHC\n");
01669     uncompress_hdr_hc06(frag_size);
01670   } else
01671 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
01672     switch(RIME_HC1_PTR[RIME_HC1_DISPATCH]) {
01673 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1
01674     case SICSLOWPAN_DISPATCH_HC1:
01675       PRINTFI("sicslowpan input: HC1\n");
01676       uncompress_hdr_hc1(frag_size);
01677       break;
01678 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC1 */
01679     case SICSLOWPAN_DISPATCH_IPV6:
01680       PRINTFI("sicslowpan input: IPV6\n");
01681       rime_hdr_len += SICSLOWPAN_IPV6_HDR_LEN;
01682 
01683       /* Put uncompressed IP header in sicslowpan_buf. */
01684       memcpy(SICSLOWPAN_IP_BUF, rime_ptr + rime_hdr_len, UIP_IPH_LEN);
01685 
01686       /* Update uncomp_hdr_len and rime_hdr_len. */
01687       rime_hdr_len += UIP_IPH_LEN;
01688       uncomp_hdr_len += UIP_IPH_LEN;
01689       break;
01690     default:
01691       /* unknown header */
01692       PRINTFI("sicslowpan input: unknown dispatch: %u\n",
01693              RIME_HC1_PTR[RIME_HC1_DISPATCH]);
01694       return;
01695   }
01696    
01697     
01698 #if SICSLOWPAN_CONF_FRAG
01699  copypayload:
01700 #endif /*SICSLOWPAN_CONF_FRAG*/
01701   /*
01702    * copy "payload" from the rime buffer to the sicslowpan_buf
01703    * if this is a first fragment or not fragmented packet,
01704    * we have already copied the compressed headers, uncomp_hdr_len
01705    * and rime_hdr_len are non 0, frag_offset is.
01706    * If this is a subsequent fragment, this is the contrary.
01707    */
01708   if(packetbuf_datalen() < rime_hdr_len) {
01709     PRINTF("SICSLOWPAN: packet dropped due to header > total packet\n");
01710     return;
01711   }
01712   rime_payload_len = packetbuf_datalen() - rime_hdr_len;
01713   memcpy((uint8_t *)SICSLOWPAN_IP_BUF + uncomp_hdr_len + (uint16_t)(frag_offset << 3), rime_ptr + rime_hdr_len, rime_payload_len);
01714   
01715   /* update processed_ip_in_len if fragment, sicslowpan_len otherwise */
01716 
01717 #if SICSLOWPAN_CONF_FRAG
01718   if(frag_size > 0) {
01719     /* Add the size of the header only for the first fragment. */
01720     if(first_fragment != 0) {
01721       processed_ip_in_len += uncomp_hdr_len;
01722     }
01723     /* For the last fragment, we are OK if there is extrenous bytes at
01724        the end of the packet. */
01725     if(last_fragment != 0) {
01726       processed_ip_in_len = frag_size;
01727     } else {
01728       processed_ip_in_len += rime_payload_len;
01729     }
01730     PRINTF("processed_ip_in_len %d, rime_payload_len %d\n", processed_ip_in_len, rime_payload_len);
01731 
01732   } else {
01733 #endif /* SICSLOWPAN_CONF_FRAG */
01734     sicslowpan_len = rime_payload_len + uncomp_hdr_len;
01735 #if SICSLOWPAN_CONF_FRAG
01736   }
01737 
01738   /*
01739    * If we have a full IP packet in sicslowpan_buf, deliver it to
01740    * the IP stack
01741    */
01742   PRINTF("sicslowpan_init processed_ip_in_len %d, sicslowpan_len %d\n",
01743          processed_ip_in_len, sicslowpan_len);
01744   if(processed_ip_in_len == 0 || (processed_ip_in_len == sicslowpan_len)) {
01745     PRINTFI("sicslowpan input: IP packet ready (length %d)\n",
01746            sicslowpan_len);
01747     memcpy((uint8_t *)UIP_IP_BUF, (uint8_t *)SICSLOWPAN_IP_BUF, sicslowpan_len);
01748     uip_len = sicslowpan_len;
01749     sicslowpan_len = 0;
01750     processed_ip_in_len = 0;
01751 #endif /* SICSLOWPAN_CONF_FRAG */
01752 
01753 #if DEBUG
01754     {
01755       uint16_t ndx;
01756       PRINTF("after decompression %u:", SICSLOWPAN_IP_BUF->len[1]);
01757       for (ndx = 0; ndx < SICSLOWPAN_IP_BUF->len[1] + 40; ndx++) {
01758         uint8_t data = ((uint8_t *) (SICSLOWPAN_IP_BUF))[ndx];
01759         PRINTF("%02x", data);
01760       }
01761       PRINTF("\n");
01762     }
01763 #endif
01764 
01765 #if SICSLOWPAN_CONF_NEIGHBOR_INFO
01766     neighbor_info_packet_received();
01767 #endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */
01768 
01769     /* if callback is set then set attributes and call */
01770     if(callback) {
01771       set_packet_attrs();
01772       callback->input_callback();
01773     }
01774 
01775     tcpip_input();
01776 #if SICSLOWPAN_CONF_FRAG
01777   }
01778 #endif /* SICSLOWPAN_CONF_FRAG */
01779 }
01780 /** @} */
01781 
01782 /*--------------------------------------------------------------------*/
01783 /* \brief 6lowpan init function (called by the MAC layer)             */
01784 /*--------------------------------------------------------------------*/
01785 void
01786 sicslowpan_init(void)
01787 {
01788   /*
01789    * Set out output function as the function to be called from uIP to
01790    * send a packet.
01791    */
01792   tcpip_set_outputfunc(output);
01793 
01794 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06
01795 /* Preinitialize any address contexts for better header compression
01796  * (Saves up to 13 bytes per 6lowpan packet)
01797  * The platform contiki-conf.h file can override this using e.g.
01798  * #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xbb;addr_contexts[0].prefix[1]=0xbb;}
01799  */
01800 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 
01801   addr_contexts[0].used   = 1;
01802   addr_contexts[0].number = 0;
01803 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0
01804         SICSLOWPAN_CONF_ADDR_CONTEXT_0;
01805 #else
01806   addr_contexts[0].prefix[0] = 0xaa; 
01807   addr_contexts[0].prefix[1] = 0xaa;
01808 #endif
01809 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */
01810 
01811 #if SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1
01812   {
01813     int i;
01814     for(i = 1; i < SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; i++) {
01815 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_1
01816           if (i==1) {
01817             addr_contexts[1].used   = 1;
01818                 addr_contexts[1].number = 1;
01819                 SICSLOWPAN_CONF_ADDR_CONTEXT_1;
01820 #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_2
01821       } else if (i==2) {
01822                 addr_contexts[2].used   = 1;
01823                 addr_contexts[2].number = 2;
01824                 SICSLOWPAN_CONF_ADDR_CONTEXT_2;
01825 #endif
01826       } else {
01827         addr_contexts[i].used = 0;
01828       }   
01829 #else
01830       addr_contexts[i].used = 0;
01831 #endif /* SICSLOWPAN_CONF_ADDR_CONTEXT_1 */
01832 
01833     }
01834   }
01835 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */
01836 
01837 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_HC06 */
01838 }
01839 /*--------------------------------------------------------------------*/
01840 const struct network_driver sicslowpan_driver = {
01841   "sicslowpan",
01842   sicslowpan_init,
01843   input
01844 };
01845 /*--------------------------------------------------------------------*/
01846 /** @} */