chameleon-bitopt.c

Go to the documentation of this file.
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  * $Id: chameleon-bitopt.c,v 1.9 2010/05/28 06:18:39 nifi Exp $
00032  */
00033 
00034 /**
00035  * \file
00036  *         A Chameleon module that produces bit-optimized headers
00037  * \author
00038  *         Adam Dunkels <adam@sics.se>
00039  */
00040 
00041 #include "net/rime/chameleon.h"
00042 
00043 #include "net/rime.h"
00044 
00045 #include <string.h>
00046 
00047 /* This option enables an optimization where the link addresses are
00048    left to the MAC RDC and not encoded in the Chameleon header.
00049    Note: this requires that the underlying MAC layer to add link
00050    addresses and will not work together with for example nullrdc.
00051  */
00052 #ifdef CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES
00053 #define CHAMELEON_WITH_MAC_LINK_ADDRESSES CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES
00054 #else /* !CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES */
00055 #define CHAMELEON_WITH_MAC_LINK_ADDRESSES 0
00056 #endif /* !CHAMELEON_CONF_WITH_MAC_LINK_ADDRESSES */
00057 
00058 struct bitopt_hdr {
00059   uint8_t channel[2];
00060 };
00061 
00062 static const uint8_t bitmask[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0,
00063                                  0xf8, 0xfc, 0xfe, 0xff };
00064 
00065 #define DEBUG 0
00066 #if DEBUG
00067 #include <stdio.h>
00068 #define PRINTF(...) printf(__VA_ARGS__)
00069 #else
00070 #define PRINTF(...)
00071 #endif
00072 
00073 /*---------------------------------------------------------------------------*/
00074 uint8_t CC_INLINE
00075 get_bits_in_byte(uint8_t *from, int bitpos, int vallen)
00076 {
00077   uint16_t shifted_val;
00078 
00079   shifted_val = (from[0] << 8) | from[1];
00080 
00081   /*  PRINTF("get_bits_in_byte: from[0] 0x%02x from[1] 0x%02x shifted_val 0x%04x, return 0x%02x vallen %d\n",
00082         from[0], from[1], shifted_val,
00083         (((shifted_val << bitpos) >> 8) & bitmask[vallen]) >> (8 - vallen),
00084         vallen
00085         );*/
00086   
00087   return (((shifted_val << bitpos) >> 8) & bitmask[vallen]) >> (8 - vallen);
00088 }
00089 /*---------------------------------------------------------------------------*/
00090 void
00091 get_bits(uint8_t *to, uint8_t *from, int bitpos, int vallen)
00092 {
00093   int i, bits;
00094   
00095   
00096   if(vallen < 8) {
00097     *to = get_bits_in_byte(from, bitpos, vallen);
00098   } else {
00099     if(bitpos == 0) {
00100       for(i = 0; i < vallen / 8; ++i) {
00101         /*      PRINTF("get_bits i %d val 0x%02x\n",
00102                 i, from[i]);*/
00103         to[i] = from[i];
00104       }
00105       bits = vallen & 7;
00106       if(bits) {
00107         to[i] = get_bits_in_byte(&from[i], 0, bits);
00108       }
00109     } else {
00110       for(i = 0; i < vallen / 8; ++i) {
00111         /*      PRINTF("get_bits i %d val 0x%02x bitpos %d\n",
00112                 i, from[i], bitpos);*/
00113         to[i] = get_bits_in_byte(&from[i], bitpos, 8);
00114       }
00115       bits = vallen & 7;
00116       if(bits) {
00117         to[i] = get_bits_in_byte(&from[i], bitpos, bits);
00118       }
00119     }
00120   }
00121 }
00122 /*---------------------------------------------------------------------------*/
00123 static int
00124 header_size(const struct packetbuf_attrlist *a)
00125 {
00126   int size, len;
00127   
00128   /* Compute the total size of the final header by summing the size of
00129      all attributes that are used on this channel. */
00130   
00131   size = 0;
00132   for(; a->type != PACKETBUF_ATTR_NONE; ++a) {
00133 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00134     if(a->type == PACKETBUF_ADDR_SENDER ||
00135        a->type == PACKETBUF_ADDR_RECEIVER) {
00136       /* Let the link layer handle sender and receiver */
00137       continue;
00138     }
00139 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */
00140     /*    PRINTF("chameleon header_size: header type %s (%d) len %d\n",
00141            packetbuf_attr_strings[a->type],
00142            a->type,
00143            a->len);*/
00144     len = a->len;
00145     /*    if(len < 8) {
00146       len = 8;
00147       }*/
00148     size += len;
00149   }
00150   return size;
00151 }
00152 /*---------------------------------------------------------------------------*/
00153 void CC_INLINE
00154 set_bits_in_byte(uint8_t *target, int bitpos, uint8_t val, int vallen)
00155 {
00156   unsigned short shifted_val;
00157   shifted_val = val << (8 - bitpos + 8 - vallen);
00158   /*  printf("set_bits_in_byte before target[0] 0x%02x target[1] 0x%02x shifted_val 0x%04x val 0x%02x vallen %d\n",
00159       target[0], target[1], shifted_val, val, vallen);*/
00160   target[0] |= shifted_val >> 8;
00161   target[1] |= shifted_val & 0xff;
00162 }
00163 /*---------------------------------------------------------------------------*/
00164 void
00165 set_bits(uint8_t *ptr, int bitpos, uint8_t *val, int vallen)
00166 {
00167   int i, bits;
00168 
00169   /*  PRINTF("set_bits %p bitpos %d, val %p len %d\n",
00170       ptr, bitpos, val, vallen);*/
00171 
00172   if(vallen < 8) {
00173     set_bits_in_byte(ptr, bitpos, *val /*>> (8 - vallen)*/, vallen);
00174   } else {
00175     if(bitpos == 0) {
00176       for(i = 0; i < vallen / 8; ++i) {
00177         /*      PRINTF("set_bits i %d val %d\n",
00178                 i, val[i]);*/
00179         ptr[i] = val[i];
00180       }
00181       bits = vallen & 7;
00182       if(bits) {
00183         set_bits_in_byte(&ptr[i], 0, val[i] >> (8 - bits), bits);
00184       }
00185     } else {
00186       for(i = 0; i < vallen / 8; ++i) {
00187         /*      PRINTF("set_bits i %d val %d\n",
00188                 i, val[i]);*/
00189         set_bits_in_byte(&ptr[i], bitpos, val[i], 8);
00190       }
00191       bits = vallen & 7;
00192       if(bits) {
00193         set_bits_in_byte(&ptr[i], 0, val[i] >> (8 - bits + bitpos), bits);
00194       }
00195     }
00196   }
00197 }
00198 /*---------------------------------------------------------------------------*/
00199 #if 0
00200 static void
00201 printbin(int n, int digits)
00202 {
00203   int i;
00204   char output[128];
00205   
00206   for(i = 0; i < digits; ++i) {
00207     output[digits - i - 1] = (n & 1) + '0';
00208     n >>= 1;
00209   }
00210   output[i] = 0;
00211   
00212   printf(output);
00213 }
00214 
00215 static void
00216 printhdr(uint8_t *hdr, int len)
00217 {
00218   int i, j;
00219 
00220   j = 0;
00221   for(i = 0; i < len; ++i) {
00222     printbin(hdr[i], 8);
00223     printf(", ");
00224     ++j;
00225     if(j == 10) {
00226       printf("\n");
00227       j = 0;
00228     }
00229   }
00230 
00231   if(j != 0) {
00232     printf("\n");
00233   }
00234 }
00235 #endif
00236 /*---------------------------------------------------------------------------*/
00237 static int
00238 pack_header(struct channel *c)
00239 {
00240   const struct packetbuf_attrlist *a;
00241   int hdrbytesize;
00242   int byteptr, bitptr, len;
00243   uint8_t *hdrptr;
00244   struct bitopt_hdr *hdr;
00245   
00246   /* Compute the total size of the final header by summing the size of
00247      all attributes that are used on this channel. */
00248 
00249   hdrbytesize = c->hdrsize / 8 + ((c->hdrsize & 7) == 0? 0: 1);
00250   if(packetbuf_hdralloc(hdrbytesize + sizeof(struct bitopt_hdr)) == 0) {
00251     PRINTF("chameleon-bitopt: insufficient space for headers\n");
00252     return 0;
00253   }
00254   hdr = (struct bitopt_hdr *)packetbuf_hdrptr();
00255   hdr->channel[0] = c->channelno & 0xff;
00256   hdr->channel[1] = (c->channelno >> 8) & 0xff;
00257 
00258   hdrptr = ((uint8_t *)packetbuf_hdrptr()) + sizeof(struct bitopt_hdr);
00259   memset(hdrptr, 0, hdrbytesize);
00260   
00261   byteptr = bitptr = 0;
00262   
00263   for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) {
00264 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00265     if(a->type == PACKETBUF_ADDR_SENDER ||
00266        a->type == PACKETBUF_ADDR_RECEIVER) {
00267       /* Let the link layer handle sender and receiver */
00268       PRINTF("%d.%d: pack_header leaving sender/receiver to link layer\n");
00269       continue;
00270     }
00271 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */
00272     PRINTF("%d.%d: pack_header type %s, len %d, bitptr %d, ",
00273            rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00274            packetbuf_attr_strings[a->type], a->len, bitptr);
00275     /*    len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0);*/
00276     len = a->len;
00277     byteptr = bitptr / 8;
00278     if(PACKETBUF_IS_ADDR(a->type)) {
00279       set_bits(&hdrptr[byteptr], bitptr & 7,
00280                (uint8_t *)packetbuf_addr(a->type), len);
00281       PRINTF("address %d.%d\n",
00282             /*      rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],*/
00283             ((uint8_t *)packetbuf_addr(a->type))[0],
00284             ((uint8_t *)packetbuf_addr(a->type))[1]);
00285     } else {
00286       packetbuf_attr_t val;
00287       val = packetbuf_attr(a->type);
00288       set_bits(&hdrptr[byteptr], bitptr & 7,
00289                (uint8_t *)&val, len);
00290       PRINTF("value %d\n",
00291             /*rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],*/
00292             val);
00293     }
00294     /*    printhdr(hdrptr, hdrbytesize);*/
00295     bitptr += len;
00296   }
00297   /*  printhdr(hdrptr, hdrbytesize);*/
00298 
00299   return 1; /* Send out packet */
00300 }
00301 /*---------------------------------------------------------------------------*/
00302 static struct channel *
00303 unpack_header(void)
00304 {
00305   const struct packetbuf_attrlist *a;
00306   int byteptr, bitptr, len;
00307   int hdrbytesize;
00308   uint8_t *hdrptr;
00309   struct bitopt_hdr *hdr;
00310   struct channel *c;
00311   
00312 
00313   /* The packet has a header that tells us what channel the packet is
00314      for. */
00315   hdr = (struct bitopt_hdr *)packetbuf_dataptr();
00316   if(packetbuf_hdrreduce(sizeof(struct bitopt_hdr)) == 0) {
00317     PRINTF("chameleon-bitopt: too short packet\n");
00318     return NULL;
00319   }
00320   c = channel_lookup((hdr->channel[1] << 8) + hdr->channel[0]);
00321   if(c == NULL) {
00322     PRINTF("chameleon-bitopt: input: channel %u not found\n",
00323            (hdr->channel[1] << 8) + hdr->channel[0]);
00324     return NULL;
00325   }
00326 
00327   hdrptr = packetbuf_dataptr();
00328   hdrbytesize = c->hdrsize / 8 + ((c->hdrsize & 7) == 0? 0: 1);
00329   if(packetbuf_hdrreduce(hdrbytesize) == 0) {
00330     PRINTF("chameleon-bitopt: too short packet\n");
00331     return NULL;
00332   }
00333   byteptr = bitptr = 0;
00334   for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) {
00335 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00336     if(a->type == PACKETBUF_ADDR_SENDER ||
00337        a->type == PACKETBUF_ADDR_RECEIVER) {
00338       /* Let the link layer handle sender and receiver */
00339       continue;
00340     }
00341 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */
00342     PRINTF("%d.%d: unpack_header type %s, len %d, bitptr %d\n",
00343            rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00344            packetbuf_attr_strings[a->type], a->len, bitptr);
00345     /*    len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0);*/
00346     len = a->len;
00347     byteptr = bitptr / 8;
00348     if(PACKETBUF_IS_ADDR(a->type)) {
00349       rimeaddr_t addr;
00350       get_bits((uint8_t *)&addr, &hdrptr[byteptr], bitptr & 7, len);
00351       PRINTF("%d.%d: unpack_header type %s, addr %d.%d\n",
00352              rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00353              packetbuf_attr_strings[a->type],
00354              addr.u8[0], addr.u8[1]);
00355       packetbuf_set_addr(a->type, &addr);
00356     } else {
00357       packetbuf_attr_t val = 0;
00358       get_bits((uint8_t *)&val, &hdrptr[byteptr], bitptr & 7, len);
00359 
00360       packetbuf_set_attr(a->type, val);
00361       PRINTF("%d.%d: unpack_header type %s, val %d\n",
00362              rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00363              packetbuf_attr_strings[a->type],
00364              val);
00365     }
00366     /*    byteptr += len / 8;*/
00367     bitptr += len;
00368   }
00369   return c;
00370 }
00371 /*---------------------------------------------------------------------------*/
00372 CC_CONST_FUNCTION struct chameleon_module chameleon_bitopt = {
00373   unpack_header,
00374   pack_header,
00375   header_size
00376 };
00377 /*---------------------------------------------------------------------------*/

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