radio-uip-uaodv.c

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: radio-uip-uaodv.c,v 1.10 2010/10/19 18:29:05 adamdunkels Exp $
00032  */
00033 
00034 #include "radio-uip-uaodv.h"
00035 #include "net/hc.h"
00036 #include "net/uip.h"
00037 #include "net/uaodv.h"
00038 #include "net/uaodv-rt.h"
00039 #include "net/uaodv-def.h"
00040 #include "lib/crc16.h"
00041 #include "list.h"
00042 #include <string.h>
00043 #include <stdio.h>
00044 
00045 /* Packet buffer size and retransmission settings */
00046 #define MAX_BUFFERED_PACKETS 10
00047 #define MAX_RETRANSMISSIONS_RREP 16
00048 #define MAX_RETRANSMISSIONS_UNICAST 16
00049 
00050 /* Forward packet (header) */
00051 #define FWD_ID "fWd:"
00052 #define FWD_ID_LENGTH 4
00053 #define FWD_NEXT_IP FWD_ID_LENGTH
00054 #define FWD_PACKET_LENGTH (FWD_NEXT_IP + 4)
00055 
00056 /* Acknowledgement packet */
00057 #define ACK_ID "aCk"
00058 #define ACK_ID_LENGTH 3
00059 #define ACK_CRC ACK_ID_LENGTH
00060 #define ACK_PACKET_LENGTH (ACK_ID_LENGTH + 2)
00061 #define ACK_TIMEOUT (CLOCK_SECOND / 50) * (random_rand() % 100)
00062 
00063 enum {
00064   EVENT_SEND_ACK
00065 };
00066 
00067 struct buf_packet {
00068   struct buf_packet *next;
00069   u8_t data[UIP_BUFSIZE];
00070   int len;
00071   u8_t resends;
00072   u8_t acked;
00073   u8_t want_ack;
00074   u16_t crc;
00075   uip_ipaddr_t finaldest;
00076   struct etimer etimer;
00077 };
00078 
00079 LIST(buf_packet_list);
00080 MEMB(buf_packet_mem, struct buf_packet, MAX_BUFFERED_PACKETS);
00081 
00082 PROCESS(radio_uip_process, "radio uIP uAODV process");
00083 
00084 static const struct radio_driver *radio;
00085 
00086 
00087 
00088 /*---------------------------------------------------------------------------*/
00089 static void receiver(const struct radio_driver *d);
00090 u8_t radio_uip_uaodv_send(void);
00091 void radio_uip_uaodv_init(const struct radio_driver *d);
00092 int radio_uip_handle_ack(u8_t *buf, int len);
00093 u16_t radio_uip_calc_crc(u8_t *buf, int len);
00094 int radio_uip_buffer_outgoing_packet(u8_t *buf, int len, uip_ipaddr_t *dest, int max_sends);
00095 int radio_uip_is_ack(u8_t *buf, int len);
00096 int radio_uip_uaodv_add_header(u8_t *buf, int len, uip_ipaddr_t *addr);
00097 int radio_uip_uaodv_remove_header(u8_t *buf, int len);
00098 void radio_uip_uaodv_change_header(u8_t *buf, int len, uip_ipaddr_t *addr);
00099 int radio_uip_uaodv_header_exists(u8_t *buf, int len);
00100 int radio_uip_uaodv_is_broadcast(uip_ipaddr_t *addr);
00101 int radio_uip_uaodv_fwd_is_broadcast(u8_t *buf, int len);
00102 int radio_uip_uaodv_fwd_is_me(u8_t *buf, int len);
00103 int radio_uip_uaodv_dest_is_me(u8_t *buf, int len);
00104 int radio_uip_uaodv_dest_port(u8_t *buf, int len);
00105 /*---------------------------------------------------------------------------*/
00106 
00107 /* Main process - handles (re)transmissions and acks */
00108 PROCESS_THREAD(radio_uip_process, ev, data)
00109 {
00110   struct buf_packet *packet;
00111 
00112   PROCESS_BEGIN();
00113 
00114   while(1) {
00115     PROCESS_YIELD();
00116 
00117     if(ev == EVENT_SEND_ACK) {
00118 
00119       /* Prepare and send ack for given 16-bit CRC */
00120       u8_t ackPacket[ACK_PACKET_LENGTH];
00121       memcpy(ackPacket, ACK_ID, ACK_ID_LENGTH);
00122       ackPacket[ACK_CRC] = ((u16_t) data >> 8);
00123       ackPacket[ACK_CRC+1] = ((u16_t) data & 0xff);
00124       radio->send(ackPacket, ACK_PACKET_LENGTH);
00125 
00126     } else if(ev == PROCESS_EVENT_TIMER) {
00127       /* Locate which packet acknowledgement timed out */
00128       for(packet = list_head(buf_packet_list);
00129           packet != NULL;
00130           packet = packet->next) {
00131         if (etimer_expired(&packet->etimer)) {
00132 
00133           if (packet->acked) {
00134             /* Already acked packet, remove silently */
00135             list_remove(buf_packet_list, packet);
00136             memb_free(&buf_packet_mem, packet);
00137 
00138           } else if (packet->resends > 0) {
00139             /* Resend packet */
00140             packet->resends--;
00141             etimer_set(&packet->etimer, ACK_TIMEOUT);
00142 
00143             radio->send(packet->data, packet->len);
00144 
00145           } else {
00146             /* Packet was resent maximum number of times */
00147 
00148             /* If an ack was expected, flag destination to bad */
00149             if (packet->want_ack && !uip_ipaddr_cmp(&packet->finaldest, &uip_broadcast_addr)) {
00150               uaodv_bad_dest(&packet->finaldest);
00151             }
00152 
00153             list_remove(buf_packet_list, packet);
00154             memb_free(&buf_packet_mem, packet);
00155           }            
00156         }
00157       }
00158     }
00159   }
00160   PROCESS_END();
00161 }
00162 /*---------------------------------------------------------------------------*/
00163 static void
00164 receiver(const struct radio_driver *d)
00165 {
00166   uip_len = d->read(&uip_buf[UIP_LLH_LEN], UIP_BUFSIZE - UIP_LLH_LEN);
00167   if (uip_len <= 0) {
00168     return;
00169   }
00170 
00171   /* Detect and handle acknowledgements */
00172   if (radio_uip_is_ack(&uip_buf[UIP_LLH_LEN], uip_len)) {
00173     radio_uip_handle_ack(&uip_buf[UIP_LLH_LEN], uip_len);
00174     return;
00175   }
00176 
00177   /* If no uAODV header, receive as usual */
00178   if (!radio_uip_uaodv_header_exists(&uip_buf[UIP_LLH_LEN], uip_len)) {
00179     tcpip_input();
00180     return;
00181   }
00182   
00183   /* Drop packet unless we are the uAODV forwarder */
00184   if (!radio_uip_uaodv_fwd_is_me(&uip_buf[UIP_LLH_LEN], uip_len)) {
00185     return;
00186   }
00187 
00188   {
00189     /* Send ack as soon as possible */
00190     u16_t crc;
00191     crc = radio_uip_calc_crc(&uip_buf[UIP_LLH_LEN], uip_len);
00192     process_post(&radio_uip_process, EVENT_SEND_ACK, (void*) (u32_t) crc);
00193   }
00194 
00195   /* Strip header and receive packet */
00196   uip_len = radio_uip_uaodv_remove_header(&uip_buf[UIP_LLH_LEN], uip_len);
00197   tcpip_input();
00198 }
00199 /*---------------------------------------------------------------------------*/
00200 u8_t
00201 radio_uip_uaodv_send(void)
00202 {
00203   struct uaodv_rt_entry *route;
00204   
00205   /* Transmit broadcast packets without header */
00206   if (radio_uip_uaodv_is_broadcast(&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr)) {
00207     return radio_uip_buffer_outgoing_packet(&uip_buf[UIP_LLH_LEN], uip_len, (void*) &uip_broadcast_addr, 1);
00208   }
00209 
00210   /* Transmit uAODV packets with headers but without using route table */
00211   if (((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->proto == UIP_PROTO_UDP
00212       && radio_uip_uaodv_dest_port(&uip_buf[UIP_LLH_LEN], uip_len) == UIP_HTONS(UAODV_UDPPORT)) {
00213     uip_ipaddr_t nexthop;
00214     memcpy(&nexthop, &((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr, 4);
00215 
00216     uip_len = radio_uip_uaodv_add_header(
00217       &uip_buf[UIP_LLH_LEN], 
00218       uip_len, 
00219       &nexthop
00220     );
00221 
00222     /* Buffer packet for persistent transmission */
00223     return radio_uip_buffer_outgoing_packet(
00224       &uip_buf[UIP_LLH_LEN],
00225       uip_len,
00226       &((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN + FWD_PACKET_LENGTH])->destipaddr,
00227       MAX_RETRANSMISSIONS_RREP);
00228   }
00229   
00230   /* Fetch already prepared uAODV route */
00231   route = uaodv_rt_lookup_any((&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr));
00232   if (route == NULL || route->is_bad) {
00233 
00234     /* If we are forwarding, notify origin of this bad route */
00235     if (tcpip_is_forwarding) {
00236       uaodv_bad_dest((&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr));
00237     }
00238       
00239     return UIP_FW_DROPPED;
00240   }
00241   
00242   /* Add header and buffer packet for persistent transmission */
00243   uip_len = radio_uip_uaodv_add_header(&uip_buf[UIP_LLH_LEN], uip_len, &route->nexthop); /* TODO Correct? */
00244   return radio_uip_buffer_outgoing_packet(
00245     &uip_buf[UIP_LLH_LEN],
00246     uip_len,
00247     &route->dest,
00248     MAX_RETRANSMISSIONS_UNICAST);
00249 }
00250 /*---------------------------------------------------------------------------*/
00251 void
00252 radio_uip_uaodv_init(const struct radio_driver *d)
00253 {
00254   /* Prepare buffers and start main process */
00255   memb_init(&buf_packet_mem);
00256   list_init(buf_packet_list);
00257   process_start(&radio_uip_process, NULL);
00258 
00259   radio = d;
00260   radio->set_receive_function(receiver);
00261   radio->on();
00262 }
00263 /*---------------------------------------------------------------------------*/
00264 u16_t
00265 radio_uip_calc_crc(u8_t *buf, int len)
00266 {
00267     u16_t crcacc = 0xffff;
00268     int counter;
00269 
00270     /* TODO Not effective */
00271     for (counter = 0; counter < len; counter++) {
00272       crcacc = crc16_add(buf[counter], crcacc);
00273     }
00274     return crcacc;
00275 }
00276 /*---------------------------------------------------------------------------*/
00277 int
00278 radio_uip_buffer_outgoing_packet(u8_t *buf, int len, uip_ipaddr_t *dest, int max_sends)
00279 {
00280   struct buf_packet *packet;
00281 
00282   u16_t crc;
00283   
00284   /* Calculate packet's unique CRC */
00285   crc = radio_uip_calc_crc(&uip_buf[UIP_LLH_LEN], uip_len);
00286 
00287   /* Check if this packet is already being transmitted */
00288   for(packet = list_head(buf_packet_list);
00289     packet != NULL;
00290     packet = packet->next) {
00291     if (packet->crc == crc) {
00292       return UIP_FW_DROPPED;
00293     }
00294   }
00295 
00296   /* Allocate storage memory */
00297   packet = (struct buf_packet *)memb_alloc(&buf_packet_mem);
00298   if (packet == NULL) {
00299     return UIP_FW_DROPPED;
00300   }
00301 
00302   /* Prepare packet buffer */
00303   memcpy(packet->data, buf, len);
00304   packet->len = len;
00305   packet->resends = max_sends;
00306   packet->acked = 0;
00307   if (packet->resends > 1)
00308     packet->want_ack = 1;
00309   else
00310     packet->want_ack = 0;
00311   memcpy(&packet->finaldest, dest, 4);
00312   packet->crc = crc;
00313 
00314   /* Set first transmission to as soon as possible */
00315   PROCESS_CONTEXT_BEGIN(&radio_uip_process);
00316   etimer_set(&packet->etimer, 0);
00317   PROCESS_CONTEXT_END(&radio_uip_process);
00318 
00319   /* Add to buffered packets list */
00320   list_add(buf_packet_list, packet);
00321 
00322   return UIP_FW_OK;
00323 }
00324 /*---------------------------------------------------------------------------*/
00325 int
00326 radio_uip_is_ack(u8_t *buf, int len)
00327 {
00328   if (len != ACK_PACKET_LENGTH)
00329     return 0;
00330   
00331   return memcmp(buf, ACK_ID, ACK_ID_LENGTH) == 0;
00332   
00333 }
00334 /*---------------------------------------------------------------------------*/
00335 int
00336 radio_uip_handle_ack(u8_t *buf, int len)
00337 {
00338   struct buf_packet *packet;
00339   u16_t ackCRC;
00340   
00341   ackCRC = (u16_t) (buf[ACK_CRC] << 8) + (u16_t) (0xff&buf[ACK_CRC+1]);
00342   
00343   /* Locate which packet was acknowledged */
00344   for(packet = list_head(buf_packet_list);
00345       packet != NULL;
00346       packet = packet->next) {
00347     if (packet->crc == ackCRC) {
00348       /* Signal packet has been acknowledged */
00349       packet->acked = 1;
00350       return 0;
00351     }
00352   }
00353 
00354   return 1;
00355 }
00356 /*---------------------------------------------------------------------------*/
00357 int
00358 radio_uip_uaodv_add_header(u8_t *buf, int len, uip_ipaddr_t *addr)
00359 {
00360   u8_t tempbuf[len];
00361   memcpy(tempbuf, buf, len);
00362   memcpy(&buf[FWD_PACKET_LENGTH], tempbuf, len);
00363   memcpy(buf, FWD_ID, FWD_ID_LENGTH);
00364   memcpy(&buf[FWD_NEXT_IP], (char*)addr, 4);
00365   return FWD_PACKET_LENGTH + len;     
00366 }
00367 /*---------------------------------------------------------------------------*/
00368 int
00369 radio_uip_uaodv_remove_header(u8_t *buf, int len)
00370 {
00371   u8_t tempbuf[len];
00372   memcpy(tempbuf, &buf[FWD_PACKET_LENGTH], len);
00373   memcpy(buf, tempbuf, len);
00374   return len - FWD_PACKET_LENGTH;
00375 }
00376 /*---------------------------------------------------------------------------*/
00377 void
00378 radio_uip_uaodv_change_header(u8_t *buf, int len, uip_ipaddr_t *addr)
00379 {
00380   memcpy(&buf[FWD_NEXT_IP], addr, 4);
00381 }
00382 /*---------------------------------------------------------------------------*/
00383 int
00384 radio_uip_uaodv_header_exists(u8_t *buf, int len)
00385 {
00386   return !memcmp(buf, FWD_ID, FWD_ID_LENGTH);
00387 }
00388 /*---------------------------------------------------------------------------*/
00389 int
00390 radio_uip_uaodv_is_broadcast(uip_ipaddr_t *addr)
00391 {
00392   return uip_ipaddr_cmp(addr, &uip_broadcast_addr);
00393 }
00394 /*---------------------------------------------------------------------------*/
00395 int
00396 radio_uip_uaodv_fwd_is_broadcast(u8_t *buf, int len)
00397 {
00398   return radio_uip_uaodv_is_broadcast((uip_ipaddr_t*) &buf[FWD_NEXT_IP]);
00399 }
00400 /*---------------------------------------------------------------------------*/
00401 int
00402 radio_uip_uaodv_fwd_is_me(u8_t *buf, int len)
00403 {
00404   return !memcmp(&buf[FWD_NEXT_IP], &uip_hostaddr, 4);
00405 }
00406 /*---------------------------------------------------------------------------*/
00407 int
00408 radio_uip_uaodv_dest_is_me(u8_t *buf, int len)
00409 {
00410   return !memcmp((&((struct uip_udpip_hdr *)buf)->destipaddr), &uip_hostaddr, 4);
00411 }
00412 /*---------------------------------------------------------------------------*/
00413 int
00414 radio_uip_uaodv_dest_port(u8_t *buf, int len)
00415 {
00416   if (len < sizeof(struct uip_udpip_hdr))
00417     return -1;
00418   return (int) ((struct uip_udpip_hdr *)buf)->destport;
00419 }
00420 /*---------------------------------------------------------------------------*/

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