Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2007, Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * This file is part of the Contiki operating system. 00030 */ 00031 00032 /** 00033 * \file 00034 * A Chameleon module that produces bit-optimized headers 00035 * \author 00036 * Adam Dunkels <adam@sics.se> 00037 */ 00038 00039 #include "net/rime/chameleon.h" 00040 00041 #include "net/rime.h" 00042 00043 #include <string.h> 00044 00045 /* This option enables an optimization where the link addresses are 00046 left to the MAC RDC and not encoded in the Chameleon header. 00047 Note: this requires that the underlying MAC layer to add link 00048 addresses and will not work together with for example nullrdc. 00049 */ 00050 #ifdef CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES 00051 #define CHAMELEON_WITH_MAC_LINK_ADDRESSES CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES 00052 #else /* !CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES */ 00053 #define CHAMELEON_WITH_MAC_LINK_ADDRESSES 0 00054 #endif /* !CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES */ 00055 00056 struct bitopt_hdr { 00057 uint8_t channel[2]; 00058 }; 00059 00060 static const uint8_t bitmask[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 00061 0xf8, 0xfc, 0xfe, 0xff }; 00062 00063 #define DEBUG 0 00064 #if DEBUG 00065 #include <stdio.h> 00066 #define PRINTF(...) printf(__VA_ARGS__) 00067 #else 00068 #define PRINTF(...) 00069 #endif 00070 00071 /*---------------------------------------------------------------------------*/ 00072 uint8_t CC_INLINE 00073 get_bits_in_byte(uint8_t *from, int bitpos, int vallen) 00074 { 00075 uint16_t shifted_val; 00076 00077 shifted_val = (from[0] << 8) | from[1]; 00078 00079 /* PRINTF("get_bits_in_byte: from[0] 0x%02x from[1] 0x%02x shifted_val 0x%04x, return 0x%02x vallen %d\n", 00080 from[0], from[1], shifted_val, 00081 (((shifted_val << bitpos) >> 8) & bitmask[vallen]) >> (8 - vallen), 00082 vallen 00083 );*/ 00084 00085 return (((shifted_val << bitpos) >> 8) & bitmask[vallen]) >> (8 - vallen); 00086 } 00087 /*---------------------------------------------------------------------------*/ 00088 void 00089 get_bits(uint8_t *to, uint8_t *from, int bitpos, int vallen) 00090 { 00091 int i, bits; 00092 00093 00094 if(vallen < 8) { 00095 *to = get_bits_in_byte(from, bitpos, vallen); 00096 } else { 00097 if(bitpos == 0) { 00098 for(i = 0; i < vallen / 8; ++i) { 00099 /* PRINTF("get_bits i %d val 0x%02x\n", 00100 i, from[i]);*/ 00101 to[i] = from[i]; 00102 } 00103 bits = vallen & 7; 00104 if(bits) { 00105 to[i] = get_bits_in_byte(&from[i], 0, bits); 00106 } 00107 } else { 00108 for(i = 0; i < vallen / 8; ++i) { 00109 /* PRINTF("get_bits i %d val 0x%02x bitpos %d\n", 00110 i, from[i], bitpos);*/ 00111 to[i] = get_bits_in_byte(&from[i], bitpos, 8); 00112 } 00113 bits = vallen & 7; 00114 if(bits) { 00115 to[i] = get_bits_in_byte(&from[i], bitpos, bits); 00116 } 00117 } 00118 } 00119 } 00120 /*---------------------------------------------------------------------------*/ 00121 static int 00122 header_size(const struct packetbuf_attrlist *a) 00123 { 00124 int size, len; 00125 00126 /* Compute the total size of the final header by summing the size of 00127 all attributes that are used on this channel. */ 00128 00129 size = 0; 00130 for(; a->type != PACKETBUF_ATTR_NONE; ++a) { 00131 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES 00132 if(a->type == PACKETBUF_ADDR_SENDER || 00133 a->type == PACKETBUF_ADDR_RECEIVER) { 00134 /* Let the link layer handle sender and receiver */ 00135 continue; 00136 } 00137 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */ 00138 /* PRINTF("chameleon header_size: header type %d len %d\n", 00139 a->type, a->len);*/ 00140 len = a->len; 00141 /* if(len < 8) { 00142 len = 8; 00143 }*/ 00144 size += len; 00145 } 00146 return size; 00147 } 00148 /*---------------------------------------------------------------------------*/ 00149 void CC_INLINE 00150 set_bits_in_byte(uint8_t *target, int bitpos, uint8_t val, int vallen) 00151 { 00152 unsigned short shifted_val; 00153 shifted_val = val << (8 - bitpos + 8 - vallen); 00154 /* printf("set_bits_in_byte before target[0] 0x%02x target[1] 0x%02x shifted_val 0x%04x val 0x%02x vallen %d\n", 00155 target[0], target[1], shifted_val, val, vallen);*/ 00156 target[0] |= shifted_val >> 8; 00157 target[1] |= shifted_val & 0xff; 00158 } 00159 /*---------------------------------------------------------------------------*/ 00160 void 00161 set_bits(uint8_t *ptr, int bitpos, uint8_t *val, int vallen) 00162 { 00163 int i, bits; 00164 00165 /* PRINTF("set_bits %p bitpos %d, val %p len %d\n", 00166 ptr, bitpos, val, vallen);*/ 00167 00168 if(vallen < 8) { 00169 set_bits_in_byte(ptr, bitpos, *val /*>> (8 - vallen)*/, vallen); 00170 } else { 00171 if(bitpos == 0) { 00172 for(i = 0; i < vallen / 8; ++i) { 00173 /* PRINTF("set_bits i %d val %d\n", 00174 i, val[i]);*/ 00175 ptr[i] = val[i]; 00176 } 00177 bits = vallen & 7; 00178 if(bits) { 00179 set_bits_in_byte(&ptr[i], 0, val[i] >> (8 - bits), bits); 00180 } 00181 } else { 00182 for(i = 0; i < vallen / 8; ++i) { 00183 /* PRINTF("set_bits i %d val %d\n", 00184 i, val[i]);*/ 00185 set_bits_in_byte(&ptr[i], bitpos, val[i], 8); 00186 } 00187 bits = vallen & 7; 00188 if(bits) { 00189 set_bits_in_byte(&ptr[i], 0, val[i] >> (8 - bits + bitpos), bits); 00190 } 00191 } 00192 } 00193 } 00194 /*---------------------------------------------------------------------------*/ 00195 #if 0 00196 static void 00197 printbin(int n, int digits) 00198 { 00199 int i; 00200 char output[128]; 00201 00202 for(i = 0; i < digits; ++i) { 00203 output[digits - i - 1] = (n & 1) + '0'; 00204 n >>= 1; 00205 } 00206 output[i] = 0; 00207 00208 printf(output); 00209 } 00210 00211 static void 00212 printhdr(uint8_t *hdr, int len) 00213 { 00214 int i, j; 00215 00216 j = 0; 00217 for(i = 0; i < len; ++i) { 00218 printbin(hdr[i], 8); 00219 printf(", "); 00220 ++j; 00221 if(j == 10) { 00222 printf("\n"); 00223 j = 0; 00224 } 00225 } 00226 00227 if(j != 0) { 00228 printf("\n"); 00229 } 00230 } 00231 #endif 00232 /*---------------------------------------------------------------------------*/ 00233 static int 00234 pack_header(struct channel *c) 00235 { 00236 const struct packetbuf_attrlist *a; 00237 int hdrbytesize; 00238 int byteptr, bitptr, len; 00239 uint8_t *hdrptr; 00240 struct bitopt_hdr *hdr; 00241 00242 /* Compute the total size of the final header by summing the size of 00243 all attributes that are used on this channel. */ 00244 00245 hdrbytesize = c->hdrsize / 8 + ((c->hdrsize & 7) == 0? 0: 1); 00246 if(packetbuf_hdralloc(hdrbytesize + sizeof(struct bitopt_hdr)) == 0) { 00247 PRINTF("chameleon-bitopt: insufficient space for headers\n"); 00248 return 0; 00249 } 00250 hdr = (struct bitopt_hdr *)packetbuf_hdrptr(); 00251 hdr->channel[0] = c->channelno & 0xff; 00252 hdr->channel[1] = (c->channelno >> 8) & 0xff; 00253 00254 hdrptr = ((uint8_t *)packetbuf_hdrptr()) + sizeof(struct bitopt_hdr); 00255 memset(hdrptr, 0, hdrbytesize); 00256 00257 byteptr = bitptr = 0; 00258 00259 for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) { 00260 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES 00261 if(a->type == PACKETBUF_ADDR_SENDER || 00262 a->type == PACKETBUF_ADDR_RECEIVER) { 00263 /* Let the link layer handle sender and receiver */ 00264 PRINTF("%d.%d: pack_header leaving sender/receiver to link layer\n"); 00265 continue; 00266 } 00267 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */ 00268 PRINTF("%d.%d: pack_header type %d, len %d, bitptr %d, ", 00269 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00270 a->type, a->len, bitptr); 00271 /* len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0);*/ 00272 len = a->len; 00273 byteptr = bitptr / 8; 00274 if(PACKETBUF_IS_ADDR(a->type)) { 00275 set_bits(&hdrptr[byteptr], bitptr & 7, 00276 (uint8_t *)packetbuf_addr(a->type), len); 00277 PRINTF("address %d.%d\n", 00278 /* rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],*/ 00279 ((uint8_t *)packetbuf_addr(a->type))[0], 00280 ((uint8_t *)packetbuf_addr(a->type))[1]); 00281 } else { 00282 packetbuf_attr_t val; 00283 val = packetbuf_attr(a->type); 00284 set_bits(&hdrptr[byteptr], bitptr & 7, 00285 (uint8_t *)&val, len); 00286 PRINTF("value %d\n", 00287 /*rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],*/ 00288 val); 00289 } 00290 /* printhdr(hdrptr, hdrbytesize);*/ 00291 bitptr += len; 00292 } 00293 /* printhdr(hdrptr, hdrbytesize);*/ 00294 00295 return 1; /* Send out packet */ 00296 } 00297 /*---------------------------------------------------------------------------*/ 00298 static struct channel * 00299 unpack_header(void) 00300 { 00301 const struct packetbuf_attrlist *a; 00302 int byteptr, bitptr, len; 00303 int hdrbytesize; 00304 uint8_t *hdrptr; 00305 struct bitopt_hdr *hdr; 00306 struct channel *c; 00307 00308 00309 /* The packet has a header that tells us what channel the packet is 00310 for. */ 00311 hdr = (struct bitopt_hdr *)packetbuf_dataptr(); 00312 if(packetbuf_hdrreduce(sizeof(struct bitopt_hdr)) == 0) { 00313 PRINTF("chameleon-bitopt: too short packet\n"); 00314 return NULL; 00315 } 00316 c = channel_lookup((hdr->channel[1] << 8) + hdr->channel[0]); 00317 if(c == NULL) { 00318 PRINTF("chameleon-bitopt: input: channel %u not found\n", 00319 (hdr->channel[1] << 8) + hdr->channel[0]); 00320 return NULL; 00321 } 00322 00323 hdrptr = packetbuf_dataptr(); 00324 hdrbytesize = c->hdrsize / 8 + ((c->hdrsize & 7) == 0? 0: 1); 00325 if(packetbuf_hdrreduce(hdrbytesize) == 0) { 00326 PRINTF("chameleon-bitopt: too short packet\n"); 00327 return NULL; 00328 } 00329 byteptr = bitptr = 0; 00330 for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) { 00331 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES 00332 if(a->type == PACKETBUF_ADDR_SENDER || 00333 a->type == PACKETBUF_ADDR_RECEIVER) { 00334 /* Let the link layer handle sender and receiver */ 00335 continue; 00336 } 00337 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */ 00338 PRINTF("%d.%d: unpack_header type %d, len %d, bitptr %d\n", 00339 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00340 a->type, a->len, bitptr); 00341 /* len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0);*/ 00342 len = a->len; 00343 byteptr = bitptr / 8; 00344 if(PACKETBUF_IS_ADDR(a->type)) { 00345 rimeaddr_t addr; 00346 get_bits((uint8_t *)&addr, &hdrptr[byteptr], bitptr & 7, len); 00347 PRINTF("%d.%d: unpack_header type %d, addr %d.%d\n", 00348 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00349 a->type, addr.u8[0], addr.u8[1]); 00350 packetbuf_set_addr(a->type, &addr); 00351 } else { 00352 packetbuf_attr_t val = 0; 00353 get_bits((uint8_t *)&val, &hdrptr[byteptr], bitptr & 7, len); 00354 00355 packetbuf_set_attr(a->type, val); 00356 PRINTF("%d.%d: unpack_header type %d, val %d\n", 00357 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00358 a->type, val); 00359 } 00360 /* byteptr += len / 8;*/ 00361 bitptr += len; 00362 } 00363 return c; 00364 } 00365 /*---------------------------------------------------------------------------*/ 00366 CC_CONST_FUNCTION struct chameleon_module chameleon_bitopt = { 00367 unpack_header, 00368 pack_header, 00369 header_size 00370 }; 00371 /*---------------------------------------------------------------------------*/