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

Generated on Mon Apr 11 14:23:31 2011 for Contiki 2.5 by  doxygen 1.6.1