Contiki 2.6
|
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 /** @} */