Contiki 2.6

uaodv.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 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: uaodv.c,v 1.38 2010/10/19 18:29:04 adamdunkels Exp $
00032  */
00033 
00034 /**
00035  * \file
00036  *         Micro implementation of the AODV ad hoc routing protocol
00037  * \author
00038  *         Adam Dunkels <adam@sics.se>
00039  */
00040 
00041 #include <stdio.h>
00042 #include <stdarg.h>
00043 
00044 #include "contiki.h"
00045 #include "net/uaodv-def.h"
00046 #include "net/uaodv-rt.h"
00047 
00048 #define NDEBUG
00049 #include "lib/assert.h"
00050 
00051 #ifdef CC2420_RADIO
00052 #include "dev/cc2420.h"
00053 #define RSSI_THRESHOLD -39      /* accept -39 ... xx */
00054 #endif
00055 
00056 /* This implementation never expires routes!!! */
00057 #define MY_ROUTE_TIMEOUT 0x7fffffff /* Should be 0xffffffff! */
00058 #define MY_NET_DIAMETER  20
00059 
00060 PROCESS(uaodv_process, "uAODV");
00061 
00062 static struct uip_udp_conn *bcastconn, *unicastconn;
00063 
00064 /* Compare sequence numbers as per RFC 3561. */
00065 #define SCMP32(a, b) ((int32_t)((a) - (b)))
00066 
00067 static CC_INLINE uint32_t
00068 last_known_seqno(uip_ipaddr_t *host)
00069 {
00070   struct uaodv_rt_entry *route = uaodv_rt_lookup_any(host);
00071 
00072   if(route != NULL)
00073     return uip_htonl(route->hseqno);
00074 
00075   return 0;
00076 }
00077 
00078 
00079 static uint32_t rreq_id, my_hseqno;     /* In host byte order! */
00080 
00081 #define NFWCACHE 16
00082 
00083 static struct {
00084   uip_ipaddr_t orig;
00085   uint32_t id;
00086 } fwcache[NFWCACHE];
00087 
00088 static CC_INLINE int
00089 fwc_lookup(const uip_ipaddr_t *orig, const uint32_t *id)
00090 {
00091   unsigned n = (orig->u8[2] + orig->u8[3]) % NFWCACHE;
00092   return fwcache[n].id == *id && uip_ipaddr_cmp(&fwcache[n].orig, orig);
00093 }
00094 
00095 static CC_INLINE void
00096 fwc_add(const uip_ipaddr_t *orig, const uint32_t *id)
00097 {
00098   unsigned n = (orig->u8[2] + orig->u8[3]) % NFWCACHE;
00099   fwcache[n].id = *id;
00100   uip_ipaddr_copy(&fwcache[n].orig, orig);
00101 }
00102 
00103 #ifdef NDEBUG
00104 #define PRINTF(...) do {} while (0)
00105 #define print_debug(...) do{}while(0)
00106 #else
00107 #define PRINTF(...) printf(__VA_ARGS__)
00108 #ifdef __GNUC__
00109 static void
00110 print_debug(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
00111 #endif /* __GNUC__ */
00112 static void
00113 print_debug(const char *fmt, ...)
00114 {
00115   va_list ap;
00116 
00117   va_start(ap, fmt);
00118   printf("%d.%d.%d.%d: ", uip_ipaddr_to_quad(&uip_hostaddr));
00119   vprintf(fmt, ap);
00120   va_end(ap);
00121   return;
00122 }
00123 #endif
00124 
00125 #define BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
00126 #define uip_udp_sender() (&BUF->srcipaddr)
00127 
00128 /*---------------------------------------------------------------------------*/
00129 static void
00130 sendto(const uip_ipaddr_t *dest, const void *buf, int len)
00131 {
00132   /* XXX: this is a HACK! We're updating the uIP UDP connection
00133      "unicastconn" so that the destination address is the next-hop,
00134      and we're patching the "uip_udp_conn" variable so that it points
00135      the this connection instead. THIS IS NOT A NICE WAY TO DO THIS,
00136      but it is currently nicer than the alternative (requesting a new
00137      poll, and remembering the state, etc.). */
00138   
00139   uip_ipaddr_copy(&unicastconn->ripaddr, dest);
00140   uip_udp_conn = unicastconn;
00141   uip_udp_packet_send(unicastconn, buf, len);
00142 }
00143 /*---------------------------------------------------------------------------*/
00144 #ifdef AODV_BAD_HOP_EXTENSION
00145 static unsigned
00146 add_rreq_extensions(void *_p)
00147 {
00148   struct uaodv_bad_hop_ext *p = _p;
00149   uip_ipaddr_t *a = p->addrs;
00150   unsigned i, n;
00151 
00152 #define SCALE_RETRANS_THRESHOLD (3*4)
00153 
00154   cc2420_check_remote(0xffff); /* Age table. */
00155   n = 0;
00156   for (i = 0; i < NNEIGBOURS; i++) {
00157     if (neigbours[i].nretrans >= SCALE_RETRANS_THRESHOLD
00158         && neigbours[i].mac != 0xffff) {
00159       a->u16[0] = uip_hostaddr.u16[0];
00160       a->u16[1] = neigbours[i].mac;
00161       n++;
00162       if(n == 15)
00163         break;                  /* Avoid buffer overrun */
00164       print_debug("BAD HOP %d.%d.%d.%d\t%d\n",
00165                   uip_ipaddr_to_quad(a), neigbours[i].nretrans);
00166     }
00167   }
00168 
00169   if(n == 0)
00170     return 0;
00171 
00172   p->type = RREQ_BAD_HOP_EXT;
00173   p->length = 2 + 4*n;          /* Two unused bytes + addresses */
00174   return 2 + p->length;         /* Type + len + extension data */
00175 }
00176 #else
00177 #define add_rreq_extensions(p) 0 /* Don't add anything */
00178 #endif
00179 
00180 static void
00181 send_rreq(uip_ipaddr_t *addr)
00182 {
00183   struct uaodv_msg_rreq *rm = (struct uaodv_msg_rreq *)uip_appdata;
00184   int len;
00185 
00186   print_debug("send RREQ for %d.%d.%d.%d\n", uip_ipaddr_to_quad(addr));
00187 
00188   rm->type = UAODV_RREQ_TYPE;
00189   rm->dest_seqno = last_known_seqno(addr);
00190   if(rm->dest_seqno == 0)
00191     rm->flags = UAODV_RREQ_UNKSEQNO;
00192   else
00193     rm->flags = 0;
00194   rm->reserved = 0;
00195   rm->hop_count = 0;
00196   rm->rreq_id = uip_htonl(rreq_id++);
00197   uip_ipaddr_copy(&rm->dest_addr, addr);
00198   uip_gethostaddr(&rm->orig_addr);
00199   my_hseqno++;                  /* Always */
00200   rm->orig_seqno = uip_htonl(my_hseqno);
00201   bcastconn->ttl = MY_NET_DIAMETER;
00202   len = sizeof(struct uaodv_msg_rreq);
00203   len += add_rreq_extensions(rm + 1);
00204   uip_udp_packet_send(bcastconn, rm, len);
00205 }
00206 /*---------------------------------------------------------------------------*/
00207 static void
00208 send_rrep(uip_ipaddr_t *dest, uip_ipaddr_t *nexthop, uip_ipaddr_t *orig,
00209           uint32_t *seqno, unsigned hop_count)
00210 {
00211   struct uaodv_msg_rrep *rm = (struct uaodv_msg_rrep *)uip_appdata;
00212   
00213   print_debug("send RREP orig=%d.%d.%d.%d hops=%d\n",
00214               uip_ipaddr_to_quad(orig), hop_count);
00215 
00216   rm->type = UAODV_RREP_TYPE;
00217   rm->flags = 0;
00218   rm->prefix_sz = 0;            /* I.e a /32 route. */
00219   rm->hop_count = hop_count;
00220   uip_ipaddr_copy(&rm->orig_addr, orig);
00221   rm->dest_seqno = *seqno;
00222   uip_ipaddr_copy(&rm->dest_addr, dest);
00223   rm->lifetime = UIP_HTONL(MY_ROUTE_TIMEOUT);
00224   sendto(nexthop, rm, sizeof(struct uaodv_msg_rrep));
00225 }
00226 /*---------------------------------------------------------------------------*/
00227 static void
00228 send_rerr(uip_ipaddr_t *addr, uint32_t *seqno)
00229 {
00230   struct uaodv_msg_rerr *rm = (struct uaodv_msg_rerr *)uip_appdata;
00231   
00232   print_debug("send RERR for %d.%d.%d.%d\n", uip_ipaddr_to_quad(addr));
00233 
00234   rm->type = UAODV_RERR_TYPE;
00235   rm->reserved = 0;
00236   rm->dest_count = 1;
00237   uip_ipaddr_copy(&rm->unreach[0].addr, addr);
00238   rm->unreach[0].seqno = *seqno;
00239   if(*seqno == 0)
00240     rm->flags = UAODV_RERR_UNKNOWN;
00241   else
00242     rm->flags = 0;
00243 
00244   uip_udp_packet_send(bcastconn, rm, sizeof(struct uaodv_msg_rerr));
00245 }
00246 /*---------------------------------------------------------------------------*/
00247 static void
00248 handle_incoming_rreq(void)
00249 {
00250   struct uaodv_msg_rreq *rm = (struct uaodv_msg_rreq *)uip_appdata;
00251   uip_ipaddr_t dest_addr, orig_addr;
00252   struct uaodv_rt_entry *rt, *fw = NULL;
00253   
00254   print_debug("RREQ %d.%d.%d.%d -> %d.%d.%d.%d ttl=%u"
00255               " orig=%d.%d.%d.%d seq=%lu hops=%u dest=%d.%d.%d.%d seq=%lu\n",
00256               uip_ipaddr_to_quad(&BUF->srcipaddr),
00257               uip_ipaddr_to_quad(&BUF->destipaddr),
00258               BUF->ttl,
00259               uip_ipaddr_to_quad(&rm->orig_addr), uip_ntohl(rm->orig_seqno),
00260               rm->hop_count,
00261               uip_ipaddr_to_quad(&rm->dest_addr), uip_ntohl(rm->dest_seqno));
00262 
00263   if(uip_ipaddr_cmp(&rm->orig_addr, &uip_hostaddr)) {
00264     return;                     /* RREQ looped back! */
00265   }
00266 
00267 #ifdef CC2420_RADIO
00268  {
00269    int ret = cc2420_check_remote(uip_udp_sender()->u16[1]);
00270 
00271    if(ret == REMOTE_YES) {
00272      print_debug("RREQ drop is remote\n");
00273      return;
00274    } else if (ret == REMOTE_NO) {
00275      /* Is neigbour, accept it. */
00276    } else if(cc2420_last_rssi < RSSI_THRESHOLD) {
00277      print_debug("RREQ drop %d %d\n", cc2420_last_rssi,
00278                  cc2420_last_correlation);
00279      return;
00280    }
00281  }
00282 #endif
00283 
00284 #ifdef AODV_BAD_HOP_EXTENSION
00285   if(uip_len > (sizeof(*rm) + 2)) {
00286     struct uaodv_bad_hop_ext *ext = (void *)(uip_appdata + sizeof(*rm));
00287     uint8_t *end = uip_appdata + uip_len;
00288     for(;
00289         (uint8_t *)ext < end;
00290         ext = (void *)((uint8_t *)ext + ext->length + 2)) {
00291       uint8_t *eend = (uint8_t *)ext + ext->length;
00292       if(eend > end)
00293         eend = end;
00294 
00295       if(ext->type == RREQ_BAD_HOP_EXT) {
00296         uip_ipaddr_t *a;
00297         for(a = ext->addrs; (uint8_t *)a < eend; a++) {
00298           if(uip_ipaddr_cmp(a, &uip_hostaddr)) {
00299             print_debug("BAD_HOP drop\n");
00300             return;
00301           }
00302         }
00303       }
00304     }
00305   }
00306 #endif /* AODV_BAD_HOP_EXTENSION */
00307 
00308   /* New reverse route? */
00309   rt = uaodv_rt_lookup(&rm->orig_addr);
00310   if(rt == NULL
00311      || (SCMP32(uip_ntohl(rm->orig_seqno), rt->hseqno) > 0) /* New route. */
00312      || (SCMP32(uip_ntohl(rm->orig_seqno), rt->hseqno) == 0
00313          && rm->hop_count < rt->hop_count)) { /* Better route. */
00314     print_debug("Inserting1\n");
00315     rt = uaodv_rt_add(&rm->orig_addr, uip_udp_sender(),
00316                       rm->hop_count, &rm->orig_seqno);
00317   }
00318     
00319   /* Check if it is for our address or a fresh route. */
00320   if(uip_ipaddr_cmp(&rm->dest_addr, &uip_hostaddr)
00321      || rm->flags & UAODV_RREQ_DESTONLY) {
00322     fw = NULL;
00323   } else {
00324     fw = uaodv_rt_lookup(&rm->dest_addr);
00325     if(!(rm->flags & UAODV_RREQ_UNKSEQNO)
00326        && fw != NULL
00327        && SCMP32(fw->hseqno, uip_ntohl(rm->dest_seqno)) <= 0) {
00328       fw = NULL;
00329     }
00330   }
00331 
00332   if (fw != NULL) {
00333     uint32_t net_seqno;
00334 
00335     print_debug("RREQ for known route\n");
00336     uip_ipaddr_copy(&dest_addr, &rm->dest_addr);
00337     uip_ipaddr_copy(&orig_addr, &rm->orig_addr);
00338     net_seqno = uip_htonl(fw->hseqno);
00339     send_rrep(&dest_addr, &rt->nexthop, &orig_addr, &net_seqno,
00340               fw->hop_count + 1);
00341   } else if(uip_ipaddr_cmp(&rm->dest_addr, &uip_hostaddr)) {
00342     uint32_t net_seqno;
00343 
00344     print_debug("RREQ for our address\n");
00345     uip_ipaddr_copy(&dest_addr, &rm->dest_addr);
00346     uip_ipaddr_copy(&orig_addr, &rm->orig_addr);
00347 
00348     my_hseqno++;
00349     if(!(rm->flags & UAODV_RREQ_UNKSEQNO)
00350        && SCMP32(my_hseqno, uip_ntohl(rm->dest_seqno)) < 0) {
00351       print_debug("New my_hseqno %lu\n", my_hseqno); /* We have rebooted. */
00352       my_hseqno = uip_ntohl(rm->dest_seqno) + 1;
00353     }
00354     net_seqno = uip_htonl(my_hseqno);
00355     send_rrep(&dest_addr, &rt->nexthop, &orig_addr, &net_seqno, 0);
00356   } else if(BUF->ttl > 1) {
00357     int len;
00358 
00359     /* Have we seen this RREQ before? */
00360     if(fwc_lookup(&rm->orig_addr, &rm->rreq_id)) {
00361       print_debug("RREQ cached, not fwd\n");
00362       return;
00363     }
00364     fwc_add(&rm->orig_addr, &rm->rreq_id);
00365 
00366     print_debug("RREQ fwd\n");
00367     rm->hop_count++;
00368     bcastconn->ttl = BUF->ttl - 1;
00369     len = sizeof(struct uaodv_msg_rreq);
00370     len += add_rreq_extensions(rm + 1);
00371     uip_udp_packet_send(bcastconn, rm, len);
00372   }
00373 }
00374 /*---------------------------------------------------------------------------*/
00375 static void
00376 handle_incoming_rrep(void)
00377 {
00378   struct uaodv_msg_rrep *rm = (struct uaodv_msg_rrep *)uip_appdata;
00379   struct uaodv_rt_entry *rt;
00380 
00381   /* Useless HELLO message? */
00382   if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) {
00383 #ifdef AODV_RESPOND_TO_HELLOS
00384     uint32_t net_seqno;
00385 #ifdef CC2420_RADIO
00386     int ret = cc2420_check_remote(uip_udp_sender()->u16[1]);
00387 
00388     if(ret == REMOTE_YES) {
00389       print_debug("HELLO drop is remote\n");
00390       return;
00391     } else if (ret == REMOTE_NO) {
00392       /* Is neigbour, accept it. */
00393     } else if(cc2420_last_rssi < RSSI_THRESHOLD) {
00394       print_debug("HELLO drop %d %d\n", cc2420_last_rssi, cc2420_last_correlation);
00395       return;
00396     }
00397 #endif
00398     /* Sometimes it helps to send a non-requested RREP in response! */
00399     net_seqno = uip_htonl(my_hseqno);
00400     send_rrep(&uip_hostaddr, &BUF->srcipaddr, &BUF->srcipaddr, &net_seqno, 0);
00401 #endif
00402     return;
00403   }
00404 
00405   print_debug("RREP %d.%d.%d.%d -> %d.%d.%d.%d"
00406               " dest=%d.%d.%d.%d seq=%lu hops=%u orig=%d.%d.%d.%d\n",
00407               uip_ipaddr_to_quad(&BUF->srcipaddr),
00408               uip_ipaddr_to_quad(&BUF->destipaddr),
00409               uip_ipaddr_to_quad(&rm->dest_addr), uip_ntohl(rm->dest_seqno),
00410               rm->hop_count,
00411               uip_ipaddr_to_quad(&rm->orig_addr));
00412 
00413   rt = uaodv_rt_lookup(&rm->dest_addr);
00414 
00415   /* New forward route? */
00416   if(rt == NULL || (SCMP32(uip_ntohl(rm->dest_seqno), rt->hseqno) > 0)) {
00417     print_debug("Inserting3\n");
00418     rt = uaodv_rt_add(&rm->dest_addr, uip_udp_sender(),
00419                       rm->hop_count, &rm->dest_seqno);
00420 #ifdef CC2420_RADIO
00421     /* This link is ok since he is unicasting back to us! */
00422     cc2420_recv_ok(uip_udp_sender());
00423     print_debug("RREP recv ok %d %d\n",
00424                 cc2420_last_rssi, cc2420_last_correlation);
00425 #endif
00426   } else {
00427     print_debug("Not inserting\n");
00428   }
00429 
00430   /* Forward RREP towards originator? */
00431   if(uip_ipaddr_cmp(&rm->orig_addr, &uip_hostaddr)) {
00432     print_debug("ROUTE FOUND\n");
00433     if(rm->flags & UAODV_RREP_ACK) {
00434       struct uaodv_msg_rrep_ack *ack = (void *)uip_appdata;
00435       ack->type = UAODV_RREP_ACK_TYPE;
00436       ack->reserved = 0;
00437       sendto(uip_udp_sender(), ack, sizeof(*ack));
00438     }
00439   } else {
00440     rt = uaodv_rt_lookup(&rm->orig_addr);
00441 
00442     if(rt == NULL) {
00443       print_debug("RREP received, but no route back to originator... :-( \n");
00444       return;
00445     }
00446 
00447     if(rm->flags & UAODV_RREP_ACK) {
00448       print_debug("RREP with ACK request (ignored)!\n");
00449       /* Don't want any RREP-ACKs in return! */
00450       rm->flags &= ~UAODV_RREP_ACK;
00451     }
00452 
00453     rm->hop_count++;
00454 
00455     print_debug("Fwd RREP to %d.%d.%d.%d\n", uip_ipaddr_to_quad(&rt->nexthop));
00456 
00457     sendto(&rt->nexthop, rm, sizeof(struct uaodv_msg_rrep));
00458   }
00459 }
00460 /*---------------------------------------------------------------------------*/
00461 static void
00462 handle_incoming_rerr(void)
00463 {
00464   struct uaodv_msg_rerr *rm = (struct uaodv_msg_rerr *)uip_appdata;
00465   struct uaodv_rt_entry *rt;
00466 
00467   print_debug("RERR %d.%d.%d.%d -> %d.%d.%d.%d"
00468               " unreach=%d.%d.%d.%d seq=%lu\n",
00469               uip_ipaddr_to_quad(&BUF->srcipaddr),
00470               uip_ipaddr_to_quad(&BUF->destipaddr),
00471               uip_ipaddr_to_quad((uip_ipaddr_t *)&rm->unreach[0]),
00472               uip_ntohl(rm->unreach[0].seqno));
00473 
00474   if(uip_ipaddr_cmp(&rm->unreach[0].addr, &uip_hostaddr))
00475     return;
00476 
00477   rt = uaodv_rt_lookup_any(&rm->unreach[0].addr);
00478   if(rt != NULL && uip_ipaddr_cmp(&rt->nexthop, uip_udp_sender())) {
00479     if((rm->flags & UAODV_RERR_UNKNOWN) || rm->unreach[0].seqno == 0
00480        || SCMP32(rt->hseqno, uip_ntohl(rm->unreach[0].seqno)) <= 0) {
00481       rt->is_bad = 1;
00482       if(rm->flags & UAODV_RERR_UNKNOWN) {
00483         rm->flags &= ~UAODV_RERR_UNKNOWN;
00484         rm->unreach[0].seqno = uip_htonl(rt->hseqno);
00485       }
00486       print_debug("RERR rebroadcast\n");
00487       uip_udp_packet_send(bcastconn, rm, sizeof(struct uaodv_msg_rerr));
00488     }
00489   }
00490 }
00491 /*---------------------------------------------------------------------------*/
00492 static void
00493 handle_incoming_packet(void)
00494 {
00495   struct uaodv_msg *m = (struct uaodv_msg *)uip_appdata;
00496 
00497   /*  print_debug("New UDP data, AODV packet type %d\n", m->type);*/
00498   switch(m->type) {
00499   case UAODV_RREQ_TYPE:
00500     handle_incoming_rreq();
00501     break;
00502 
00503   case UAODV_RREP_TYPE:
00504     handle_incoming_rrep();
00505     break;
00506 
00507   case UAODV_RERR_TYPE:
00508     handle_incoming_rerr();
00509     break;
00510   }
00511 
00512 }
00513 /*---------------------------------------------------------------------------*/
00514 static enum {
00515   COMMAND_NONE,
00516   COMMAND_SEND_RREQ,
00517   COMMAND_SEND_RERR,
00518 } command;
00519 
00520 static uip_ipaddr_t bad_dest;
00521 static uint32_t bad_seqno;              /* In network byte order! */
00522 
00523 void
00524 uaodv_bad_dest(uip_ipaddr_t *dest)
00525 {
00526   struct uaodv_rt_entry *rt = uaodv_rt_lookup_any(dest);
00527 
00528   if(rt == NULL)
00529     bad_seqno = 0;              /* Or flag this in RERR? */
00530   else {
00531     rt->is_bad = 1;
00532     bad_seqno = uip_htonl(rt->hseqno);
00533   }
00534 
00535   uip_ipaddr_copy(&bad_dest, dest);
00536   command = COMMAND_SEND_RERR;
00537   process_post(&uaodv_process, PROCESS_EVENT_MSG, NULL);
00538 }
00539 
00540 static uip_ipaddr_t rreq_addr;
00541 static struct timer next_time;
00542 
00543 struct uaodv_rt_entry *
00544 uaodv_request_route_to(uip_ipaddr_t *host)
00545 {
00546   struct uaodv_rt_entry *route = uaodv_rt_lookup(host);
00547 
00548   if(route != NULL) {
00549     uaodv_rt_lru(route);
00550     return route;
00551   }
00552 
00553   /*
00554    * Broadcast protocols must be rate-limited!
00555    */
00556   if(!timer_expired(&next_time)) {
00557     return NULL;
00558   }
00559 
00560   if(command != COMMAND_NONE) {
00561     return NULL;
00562   }
00563 
00564   uip_ipaddr_copy(&rreq_addr, host);
00565   command = COMMAND_SEND_RREQ;
00566   process_post(&uaodv_process, PROCESS_EVENT_MSG, NULL);
00567   timer_set(&next_time, CLOCK_SECOND/8); /* Max 10/s per RFC3561. */
00568   return NULL;
00569 }
00570 
00571 PROCESS_THREAD(uaodv_process, ev, data)
00572 {
00573   PROCESS_EXITHANDLER(goto exit);
00574 
00575   PROCESS_BEGIN();
00576 
00577   printf("uaodv_process starting %lu\n", (unsigned long) my_hseqno);
00578 
00579   bcastconn = udp_broadcast_new(UIP_HTONS(UAODV_UDPPORT), NULL);
00580   unicastconn = udp_broadcast_new(UIP_HTONS(UAODV_UDPPORT), NULL);
00581   
00582   while(1) {
00583     PROCESS_WAIT_EVENT();
00584 
00585     if(ev == tcpip_event) {
00586       if(uip_newdata()) {
00587         handle_incoming_packet();
00588         continue;
00589       }
00590       if(uip_poll()) {
00591         if(command == COMMAND_SEND_RREQ) {
00592           if(uaodv_rt_lookup(&rreq_addr) == NULL)
00593             send_rreq(&rreq_addr);
00594         } else if (command == COMMAND_SEND_RERR) {
00595           send_rerr(&bad_dest, &bad_seqno);
00596         }
00597         command = COMMAND_NONE;
00598         continue;
00599       }
00600     }
00601 
00602     if(ev == PROCESS_EVENT_MSG) {
00603       tcpip_poll_udp(bcastconn);
00604     }
00605   }
00606 
00607  exit:
00608   command = COMMAND_NONE;
00609   uaodv_rt_flush_all();
00610   uip_udp_remove(bcastconn);
00611   bcastconn = NULL;
00612   uip_udp_remove(unicastconn);
00613   unicastconn = NULL;
00614   printf("uaodv_process exiting\n");
00615   PROCESS_END();
00616 }
00617 /*---------------------------------------------------------------------------*/