Contiki 2.6
|
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 /*---------------------------------------------------------------------------*/