Contiki 2.6

chameleon-raw.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  */
00032 
00033 /**
00034  * \file
00035  *         A Chameleon module that produces non-optimized headers
00036  * \author
00037  *         Adam Dunkels <adam@sics.se>
00038  */
00039 
00040 #include <string.h>
00041 
00042 #include "net/rime/chameleon.h"
00043 #include "net/rime.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 #define DEBUG 0
00057 #if DEBUG
00058 #include <stdio.h>
00059 #define PRINTF(...) printf(__VA_ARGS__)
00060 #else
00061 #define PRINTF(...)
00062 #endif
00063 
00064 struct raw_hdr {
00065   uint8_t channel[2];
00066 };
00067 
00068 /*---------------------------------------------------------------------------*/
00069 static struct channel *
00070 input(void)
00071 {
00072   const struct packetbuf_attrlist *a;
00073   int byteptr, bitptr, len;
00074   uint8_t *hdrptr;
00075   struct raw_hdr *hdr;
00076   struct channel *c;
00077 
00078   /* The packet has a header that tells us what channel the packet is
00079      for. */
00080   hdr = (struct raw_hdr *)packetbuf_dataptr();
00081   if(packetbuf_hdrreduce(sizeof(struct raw_hdr)) == 0) {
00082     PRINTF("chameleon-raw: too short packet\n");
00083     return NULL;
00084   }
00085   c = channel_lookup((hdr->channel[1] << 8) + hdr->channel[0]);
00086   if(c == NULL) {
00087     PRINTF("chameleon-raw: input: channel %u not found\n",
00088            (hdr->channel[1] << 8) + hdr->channel[0]);
00089     return NULL;
00090   }
00091 
00092   hdrptr = packetbuf_dataptr();
00093   if(packetbuf_hdrreduce(c->hdrsize) == 0) {
00094     PRINTF("chameleon-raw: too short packet\n");
00095     return NULL;
00096   }
00097   byteptr = bitptr = 0;
00098   for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) {
00099 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00100     if(a->type == PACKETBUF_ADDR_SENDER ||
00101        a->type == PACKETBUF_ADDR_RECEIVER) {
00102       /* Let the link layer handle sender and receiver */
00103       continue;
00104     }
00105 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */
00106     PRINTF("%d.%d: unpack_header type %d, len %d\n",
00107            rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00108            a->type, a->len);
00109     len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0);
00110     if(PACKETBUF_IS_ADDR(a->type)) {
00111       const rimeaddr_t addr;
00112       memcpy((uint8_t *)&addr, &hdrptr[byteptr], len / 8);
00113       PRINTF("%d.%d: unpack_header type %d, addr %d.%d\n",
00114              rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00115              a->type, addr.u8[0], addr.u8[1]);
00116       packetbuf_set_addr(a->type, &addr);
00117     } else {
00118       packetbuf_attr_t val = 0;
00119       memcpy((uint8_t *)&val, &hdrptr[byteptr], len / 8);
00120 
00121       packetbuf_set_attr(a->type, val);
00122       PRINTF("%d.%d: unpack_header type %d, val %d\n",
00123              rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00124              a->type, val);
00125     }
00126     byteptr += len / 8;
00127   }
00128   return c;
00129 }
00130 /*---------------------------------------------------------------------------*/
00131 static int
00132 output(struct channel *c)
00133 {
00134   const struct packetbuf_attrlist *a;
00135   int byteptr, len;
00136   uint8_t *hdrptr;
00137   struct raw_hdr *hdr;
00138   
00139   /* Compute the total size of the final header by summing the size of
00140      all attributes that are used on this channel. */
00141   if(packetbuf_hdralloc(c->hdrsize + sizeof(struct raw_hdr)) == 0) {
00142     PRINTF("chameleon-raw: insufficient space for headers\n");
00143     return 0;
00144   }
00145   hdr = (struct raw_hdr *)packetbuf_hdrptr();
00146   hdr->channel[0] = c->channelno & 0xff;
00147   hdr->channel[1] = (c->channelno >> 8) & 0xff;
00148 
00149   hdrptr = ((uint8_t *)packetbuf_hdrptr()) + sizeof(struct raw_hdr);
00150   byteptr = 0;
00151   for(a = c->attrlist; a->type != PACKETBUF_ATTR_NONE; ++a) {
00152 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00153     if(a->type == PACKETBUF_ADDR_SENDER ||
00154        a->type == PACKETBUF_ADDR_RECEIVER) {
00155       /* Let the link layer handle sender and receiver */
00156       PRINTF("%d.%d: pack_header leaving sender/receiver to link layer\n");
00157       continue;
00158     }
00159 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */
00160     PRINTF("%d.%d: pack_header type %d, len %d\n",
00161            rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00162            a->type, a->len);
00163     len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0);
00164     if(PACKETBUF_IS_ADDR(a->type)) {
00165       const rimeaddr_t *rimeaddr;
00166       /*      memcpy(&hdrptr[byteptr], (uint8_t *)packetbuf_attr_aget(a->type), len / 8);*/
00167       rimeaddr = packetbuf_addr(a->type);
00168       hdrptr[byteptr] = rimeaddr->u8[0];
00169       hdrptr[byteptr + 1] = rimeaddr->u8[1];
00170       
00171       PRINTF("%d.%d: address %d.%d\n",
00172             rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00173             ((uint8_t *)packetbuf_addr(a->type))[0],
00174             ((uint8_t *)packetbuf_addr(a->type))[1]);
00175     } else {
00176       packetbuf_attr_t val;
00177       val = packetbuf_attr(a->type);
00178       memcpy(&hdrptr[byteptr], &val, len / 8);
00179       PRINTF("%d.%d: value %d\n",
00180             rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
00181             val);
00182     }
00183     byteptr += len / 8;
00184   }
00185 
00186   return 1; /* Send out packet */
00187 }
00188 /*---------------------------------------------------------------------------*/
00189 static int
00190 hdrsize(const struct packetbuf_attrlist *a)
00191 {
00192   int size, len;
00193   
00194   /* Compute the total size of the final header by summing the size of
00195      all attributes that are used on this channel. */
00196   
00197   size = 0;
00198   for(; a->type != PACKETBUF_ATTR_NONE; ++a) {
00199     /*    PRINTF("chameleon header_size: header type %d len %d\n",
00200            a->type, a->len);*/
00201 #if CHAMELEON_WITH_MAC_LINK_ADDRESSES
00202     if(a->type == PACKETBUF_ADDR_SENDER ||
00203        a->type == PACKETBUF_ADDR_RECEIVER) {
00204       /* Let the mac layer handle the sender and receiver */
00205       continue;
00206     }
00207 #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */
00208     len = a->len;
00209     if(len < 8) {
00210       len = 8;
00211     }
00212     size += len;
00213   }
00214   return size / 8;
00215 }
00216 /*---------------------------------------------------------------------------*/
00217 CC_CONST_FUNCTION struct chameleon_module chameleon_raw = { input, output,
00218                                                             hdrsize };