Contiki 2.5
uaodv.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * $Id: uaodv.c,v 1.38 2010/10/19 18:29:04 adamdunkels Exp $
32  */
33 
34 /**
35  * \file
36  * Micro implementation of the AODV ad hoc routing protocol
37  * \author
38  * Adam Dunkels <adam@sics.se>
39  */
40 
41 #include <stdio.h>
42 #include <stdarg.h>
43 
44 #include "contiki.h"
45 #include "net/uaodv-def.h"
46 #include "net/uaodv-rt.h"
47 
48 #define NDEBUG
49 #include "lib/assert.h"
50 
51 #ifdef CC2420_RADIO
52 #include "dev/cc2420.h"
53 #define RSSI_THRESHOLD -39 /* accept -39 ... xx */
54 #endif
55 
56 /* This implementation never expires routes!!! */
57 #define MY_ROUTE_TIMEOUT 0x7fffffff /* Should be 0xffffffff! */
58 #define MY_NET_DIAMETER 20
59 
60 PROCESS(uaodv_process, "uAODV");
61 
62 static struct uip_udp_conn *bcastconn, *unicastconn;
63 
64 /* Compare sequence numbers as per RFC 3561. */
65 #define SCMP32(a, b) ((s32_t)((a) - (b)))
66 
67 static CC_INLINE u32_t
68 last_known_seqno(uip_ipaddr_t *host)
69 {
70  struct uaodv_rt_entry *route = uaodv_rt_lookup_any(host);
71 
72  if(route != NULL)
73  return uip_htonl(route->hseqno);
74 
75  return 0;
76 }
77 
78 
79 static u32_t rreq_id, my_hseqno; /* In host byte order! */
80 
81 #define NFWCACHE 16
82 
83 static struct {
84  uip_ipaddr_t orig;
85  u32_t id;
86 } fwcache[NFWCACHE];
87 
88 static CC_INLINE int
89 fwc_lookup(const uip_ipaddr_t *orig, const u32_t *id)
90 {
91  unsigned n = (orig->u8[2] + orig->u8[3]) % NFWCACHE;
92  return fwcache[n].id == *id && uip_ipaddr_cmp(&fwcache[n].orig, orig);
93 }
94 
95 static CC_INLINE void
96 fwc_add(const uip_ipaddr_t *orig, const u32_t *id)
97 {
98  unsigned n = (orig->u8[2] + orig->u8[3]) % NFWCACHE;
99  fwcache[n].id = *id;
100  uip_ipaddr_copy(&fwcache[n].orig, orig);
101 }
102 
103 #ifdef NDEBUG
104 #define PRINTF(...) do {} while (0)
105 #define print_debug(...) do{}while(0)
106 #else
107 #define PRINTF(...) printf(__VA_ARGS__)
108 #ifdef __GNUC__
109 static void
110 print_debug(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
111 #endif /* __GNUC__ */
112 static void
113 print_debug(const char *fmt, ...)
114 {
115  va_list ap;
116 
117  va_start(ap, fmt);
118  printf("%d.%d.%d.%d: ", uip_ipaddr_to_quad(&uip_hostaddr));
119  vprintf(fmt, ap);
120  va_end(ap);
121  return;
122 }
123 #endif
124 
125 #define BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
126 #define uip_udp_sender() (&BUF->srcipaddr)
127 
128 /*---------------------------------------------------------------------------*/
129 static void
130 sendto(const uip_ipaddr_t *dest, const void *buf, int len)
131 {
132  /* XXX: this is a HACK! We're updating the uIP UDP connection
133  "unicastconn" so that the destination address is the next-hop,
134  and we're patching the "uip_udp_conn" variable so that it points
135  the this connection instead. THIS IS NOT A NICE WAY TO DO THIS,
136  but it is currently nicer than the alternative (requesting a new
137  poll, and remembering the state, etc.). */
138 
139  uip_ipaddr_copy(&unicastconn->ripaddr, dest);
140  uip_udp_conn = unicastconn;
141  uip_udp_packet_send(unicastconn, buf, len);
142 }
143 /*---------------------------------------------------------------------------*/
144 #ifdef AODV_BAD_HOP_EXTENSION
145 static unsigned
146 add_rreq_extensions(void *_p)
147 {
148  struct uaodv_bad_hop_ext *p = _p;
149  uip_ipaddr_t *a = p->addrs;
150  unsigned i, n;
151 
152 #define SCALE_RETRANS_THRESHOLD (3*4)
153 
154  cc2420_check_remote(0xffff); /* Age table. */
155  n = 0;
156  for (i = 0; i < NNEIGBOURS; i++) {
157  if (neigbours[i].nretrans >= SCALE_RETRANS_THRESHOLD
158  && neigbours[i].mac != 0xffff) {
159  a->u16[0] = uip_hostaddr.u16[0];
160  a->u16[1] = neigbours[i].mac;
161  n++;
162  if(n == 15)
163  break; /* Avoid buffer overrun */
164  print_debug("BAD HOP %d.%d.%d.%d\t%d\n",
165  uip_ipaddr_to_quad(a), neigbours[i].nretrans);
166  }
167  }
168 
169  if(n == 0)
170  return 0;
171 
172  p->type = RREQ_BAD_HOP_EXT;
173  p->length = 2 + 4*n; /* Two unused bytes + addresses */
174  return 2 + p->length; /* Type + len + extension data */
175 }
176 #else
177 #define add_rreq_extensions(p) 0 /* Don't add anything */
178 #endif
179 
180 static void
181 send_rreq(uip_ipaddr_t *addr)
182 {
183  struct uaodv_msg_rreq *rm = (struct uaodv_msg_rreq *)uip_appdata;
184  int len;
185 
186  print_debug("send RREQ for %d.%d.%d.%d\n", uip_ipaddr_to_quad(addr));
187 
188  rm->type = UAODV_RREQ_TYPE;
189  rm->dest_seqno = last_known_seqno(addr);
190  if(rm->dest_seqno == 0)
191  rm->flags = UAODV_RREQ_UNKSEQNO;
192  else
193  rm->flags = 0;
194  rm->reserved = 0;
195  rm->hop_count = 0;
196  rm->rreq_id = uip_htonl(rreq_id++);
197  uip_ipaddr_copy(&rm->dest_addr, addr);
198  uip_gethostaddr(&rm->orig_addr);
199  my_hseqno++; /* Always */
200  rm->orig_seqno = uip_htonl(my_hseqno);
201  bcastconn->ttl = MY_NET_DIAMETER;
202  len = sizeof(struct uaodv_msg_rreq);
203  len += add_rreq_extensions(rm + 1);
204  uip_udp_packet_send(bcastconn, rm, len);
205 }
206 /*---------------------------------------------------------------------------*/
207 static void
208 send_rrep(uip_ipaddr_t *dest, uip_ipaddr_t *nexthop, uip_ipaddr_t *orig,
209  u32_t *seqno, unsigned hop_count)
210 {
211  struct uaodv_msg_rrep *rm = (struct uaodv_msg_rrep *)uip_appdata;
212 
213  print_debug("send RREP orig=%d.%d.%d.%d hops=%d\n",
214  uip_ipaddr_to_quad(orig), hop_count);
215 
216  rm->type = UAODV_RREP_TYPE;
217  rm->flags = 0;
218  rm->prefix_sz = 0; /* I.e a /32 route. */
219  rm->hop_count = hop_count;
220  uip_ipaddr_copy(&rm->orig_addr, orig);
221  rm->dest_seqno = *seqno;
222  uip_ipaddr_copy(&rm->dest_addr, dest);
223  rm->lifetime = UIP_HTONL(MY_ROUTE_TIMEOUT);
224  sendto(nexthop, rm, sizeof(struct uaodv_msg_rrep));
225 }
226 /*---------------------------------------------------------------------------*/
227 static void
228 send_rerr(uip_ipaddr_t *addr, u32_t *seqno)
229 {
230  struct uaodv_msg_rerr *rm = (struct uaodv_msg_rerr *)uip_appdata;
231 
232  print_debug("send RERR for %d.%d.%d.%d\n", uip_ipaddr_to_quad(addr));
233 
234  rm->type = UAODV_RERR_TYPE;
235  rm->reserved = 0;
236  rm->dest_count = 1;
237  uip_ipaddr_copy(&rm->unreach[0].addr, addr);
238  rm->unreach[0].seqno = *seqno;
239  if(*seqno == 0)
240  rm->flags = UAODV_RERR_UNKNOWN;
241  else
242  rm->flags = 0;
243 
244  uip_udp_packet_send(bcastconn, rm, sizeof(struct uaodv_msg_rerr));
245 }
246 /*---------------------------------------------------------------------------*/
247 static void
248 handle_incoming_rreq(void)
249 {
250  struct uaodv_msg_rreq *rm = (struct uaodv_msg_rreq *)uip_appdata;
251  uip_ipaddr_t dest_addr, orig_addr;
252  struct uaodv_rt_entry *rt, *fw = NULL;
253 
254  print_debug("RREQ %d.%d.%d.%d -> %d.%d.%d.%d ttl=%u"
255  " orig=%d.%d.%d.%d seq=%lu hops=%u dest=%d.%d.%d.%d seq=%lu\n",
256  uip_ipaddr_to_quad(&BUF->srcipaddr),
257  uip_ipaddr_to_quad(&BUF->destipaddr),
258  BUF->ttl,
259  uip_ipaddr_to_quad(&rm->orig_addr), uip_ntohl(rm->orig_seqno),
260  rm->hop_count,
261  uip_ipaddr_to_quad(&rm->dest_addr), uip_ntohl(rm->dest_seqno));
262 
263  if(uip_ipaddr_cmp(&rm->orig_addr, &uip_hostaddr)) {
264  return; /* RREQ looped back! */
265  }
266 
267 #ifdef CC2420_RADIO
268  {
269  int ret = cc2420_check_remote(uip_udp_sender()->u16[1]);
270 
271  if(ret == REMOTE_YES) {
272  print_debug("RREQ drop is remote\n");
273  return;
274  } else if (ret == REMOTE_NO) {
275  /* Is neigbour, accept it. */
276  } else if(cc2420_last_rssi < RSSI_THRESHOLD) {
277  print_debug("RREQ drop %d %d\n", cc2420_last_rssi,
278  cc2420_last_correlation);
279  return;
280  }
281  }
282 #endif
283 
284 #ifdef AODV_BAD_HOP_EXTENSION
285  if(uip_len > (sizeof(*rm) + 2)) {
286  struct uaodv_bad_hop_ext *ext = (void *)(uip_appdata + sizeof(*rm));
287  u8_t *end = uip_appdata + uip_len;
288  for(;
289  (u8_t *)ext < end;
290  ext = (void *)((u8_t *)ext + ext->length + 2)) {
291  u8_t *eend = (u8_t *)ext + ext->length;
292  if(eend > end)
293  eend = end;
294 
295  if(ext->type == RREQ_BAD_HOP_EXT) {
296  uip_ipaddr_t *a;
297  for(a = ext->addrs; (u8_t *)a < eend; a++) {
298  if(uip_ipaddr_cmp(a, &uip_hostaddr)) {
299  print_debug("BAD_HOP drop\n");
300  return;
301  }
302  }
303  }
304  }
305  }
306 #endif /* AODV_BAD_HOP_EXTENSION */
307 
308  /* New reverse route? */
309  rt = uaodv_rt_lookup(&rm->orig_addr);
310  if(rt == NULL
311  || (SCMP32(uip_ntohl(rm->orig_seqno), rt->hseqno) > 0) /* New route. */
312  || (SCMP32(uip_ntohl(rm->orig_seqno), rt->hseqno) == 0
313  && rm->hop_count < rt->hop_count)) { /* Better route. */
314  print_debug("Inserting1\n");
315  rt = uaodv_rt_add(&rm->orig_addr, uip_udp_sender(),
316  rm->hop_count, &rm->orig_seqno);
317  }
318 
319  /* Check if it is for our address or a fresh route. */
320  if(uip_ipaddr_cmp(&rm->dest_addr, &uip_hostaddr)
321  || rm->flags & UAODV_RREQ_DESTONLY) {
322  fw = NULL;
323  } else {
324  fw = uaodv_rt_lookup(&rm->dest_addr);
325  if(!(rm->flags & UAODV_RREQ_UNKSEQNO)
326  && fw != NULL
327  && SCMP32(fw->hseqno, uip_ntohl(rm->dest_seqno)) <= 0) {
328  fw = NULL;
329  }
330  }
331 
332  if (fw != NULL) {
333  u32_t net_seqno;
334 
335  print_debug("RREQ for known route\n");
336  uip_ipaddr_copy(&dest_addr, &rm->dest_addr);
337  uip_ipaddr_copy(&orig_addr, &rm->orig_addr);
338  net_seqno = uip_htonl(fw->hseqno);
339  send_rrep(&dest_addr, &rt->nexthop, &orig_addr, &net_seqno,
340  fw->hop_count + 1);
341  } else if(uip_ipaddr_cmp(&rm->dest_addr, &uip_hostaddr)) {
342  u32_t net_seqno;
343 
344  print_debug("RREQ for our address\n");
345  uip_ipaddr_copy(&dest_addr, &rm->dest_addr);
346  uip_ipaddr_copy(&orig_addr, &rm->orig_addr);
347 
348  my_hseqno++;
349  if(!(rm->flags & UAODV_RREQ_UNKSEQNO)
350  && SCMP32(my_hseqno, uip_ntohl(rm->dest_seqno)) < 0) {
351  print_debug("New my_hseqno %lu\n", my_hseqno); /* We have rebooted. */
352  my_hseqno = uip_ntohl(rm->dest_seqno) + 1;
353  }
354  net_seqno = uip_htonl(my_hseqno);
355  send_rrep(&dest_addr, &rt->nexthop, &orig_addr, &net_seqno, 0);
356  } else if(BUF->ttl > 1) {
357  int len;
358 
359  /* Have we seen this RREQ before? */
360  if(fwc_lookup(&rm->orig_addr, &rm->rreq_id)) {
361  print_debug("RREQ cached, not fwd\n");
362  return;
363  }
364  fwc_add(&rm->orig_addr, &rm->rreq_id);
365 
366  print_debug("RREQ fwd\n");
367  rm->hop_count++;
368  bcastconn->ttl = BUF->ttl - 1;
369  len = sizeof(struct uaodv_msg_rreq);
370  len += add_rreq_extensions(rm + 1);
371  uip_udp_packet_send(bcastconn, rm, len);
372  }
373 }
374 /*---------------------------------------------------------------------------*/
375 static void
376 handle_incoming_rrep(void)
377 {
378  struct uaodv_msg_rrep *rm = (struct uaodv_msg_rrep *)uip_appdata;
379  struct uaodv_rt_entry *rt;
380 
381  /* Useless HELLO message? */
382  if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) {
383 #ifdef AODV_RESPOND_TO_HELLOS
384  u32_t net_seqno;
385 #ifdef CC2420_RADIO
386  int ret = cc2420_check_remote(uip_udp_sender()->u16[1]);
387 
388  if(ret == REMOTE_YES) {
389  print_debug("HELLO drop is remote\n");
390  return;
391  } else if (ret == REMOTE_NO) {
392  /* Is neigbour, accept it. */
393  } else if(cc2420_last_rssi < RSSI_THRESHOLD) {
394  print_debug("HELLO drop %d %d\n", cc2420_last_rssi, cc2420_last_correlation);
395  return;
396  }
397 #endif
398  /* Sometimes it helps to send a non-requested RREP in response! */
399  net_seqno = uip_htonl(my_hseqno);
400  send_rrep(&uip_hostaddr, &BUF->srcipaddr, &BUF->srcipaddr, &net_seqno, 0);
401 #endif
402  return;
403  }
404 
405  print_debug("RREP %d.%d.%d.%d -> %d.%d.%d.%d"
406  " dest=%d.%d.%d.%d seq=%lu hops=%u orig=%d.%d.%d.%d\n",
407  uip_ipaddr_to_quad(&BUF->srcipaddr),
408  uip_ipaddr_to_quad(&BUF->destipaddr),
409  uip_ipaddr_to_quad(&rm->dest_addr), uip_ntohl(rm->dest_seqno),
410  rm->hop_count,
411  uip_ipaddr_to_quad(&rm->orig_addr));
412 
413  rt = uaodv_rt_lookup(&rm->dest_addr);
414 
415  /* New forward route? */
416  if(rt == NULL || (SCMP32(uip_ntohl(rm->dest_seqno), rt->hseqno) > 0)) {
417  print_debug("Inserting3\n");
418  rt = uaodv_rt_add(&rm->dest_addr, uip_udp_sender(),
419  rm->hop_count, &rm->dest_seqno);
420 #ifdef CC2420_RADIO
421  /* This link is ok since he is unicasting back to us! */
422  cc2420_recv_ok(uip_udp_sender());
423  print_debug("RREP recv ok %d %d\n",
424  cc2420_last_rssi, cc2420_last_correlation);
425 #endif
426  } else {
427  print_debug("Not inserting\n");
428  }
429 
430  /* Forward RREP towards originator? */
431  if(uip_ipaddr_cmp(&rm->orig_addr, &uip_hostaddr)) {
432  print_debug("ROUTE FOUND\n");
433  if(rm->flags & UAODV_RREP_ACK) {
434  struct uaodv_msg_rrep_ack *ack = (void *)uip_appdata;
435  ack->type = UAODV_RREP_ACK_TYPE;
436  ack->reserved = 0;
437  sendto(uip_udp_sender(), ack, sizeof(*ack));
438  }
439  } else {
440  rt = uaodv_rt_lookup(&rm->orig_addr);
441 
442  if(rt == NULL) {
443  print_debug("RREP received, but no route back to originator... :-( \n");
444  return;
445  }
446 
447  if(rm->flags & UAODV_RREP_ACK) {
448  print_debug("RREP with ACK request (ignored)!\n");
449  /* Don't want any RREP-ACKs in return! */
450  rm->flags &= ~UAODV_RREP_ACK;
451  }
452 
453  rm->hop_count++;
454 
455  print_debug("Fwd RREP to %d.%d.%d.%d\n", uip_ipaddr_to_quad(&rt->nexthop));
456 
457  sendto(&rt->nexthop, rm, sizeof(struct uaodv_msg_rrep));
458  }
459 }
460 /*---------------------------------------------------------------------------*/
461 static void
462 handle_incoming_rerr(void)
463 {
464  struct uaodv_msg_rerr *rm = (struct uaodv_msg_rerr *)uip_appdata;
465  struct uaodv_rt_entry *rt;
466 
467  print_debug("RERR %d.%d.%d.%d -> %d.%d.%d.%d"
468  " unreach=%d.%d.%d.%d seq=%lu\n",
469  uip_ipaddr_to_quad(&BUF->srcipaddr),
470  uip_ipaddr_to_quad(&BUF->destipaddr),
471  uip_ipaddr_to_quad((uip_ipaddr_t *)&rm->unreach[0]),
472  uip_ntohl(rm->unreach[0].seqno));
473 
474  if(uip_ipaddr_cmp(&rm->unreach[0].addr, &uip_hostaddr))
475  return;
476 
477  rt = uaodv_rt_lookup_any(&rm->unreach[0].addr);
478  if(rt != NULL && uip_ipaddr_cmp(&rt->nexthop, uip_udp_sender())) {
479  if((rm->flags & UAODV_RERR_UNKNOWN) || rm->unreach[0].seqno == 0
480  || SCMP32(rt->hseqno, uip_ntohl(rm->unreach[0].seqno)) <= 0) {
481  rt->is_bad = 1;
482  if(rm->flags & UAODV_RERR_UNKNOWN) {
483  rm->flags &= ~UAODV_RERR_UNKNOWN;
484  rm->unreach[0].seqno = uip_htonl(rt->hseqno);
485  }
486  print_debug("RERR rebroadcast\n");
487  uip_udp_packet_send(bcastconn, rm, sizeof(struct uaodv_msg_rerr));
488  }
489  }
490 }
491 /*---------------------------------------------------------------------------*/
492 static void
493 handle_incoming_packet(void)
494 {
495  struct uaodv_msg *m = (struct uaodv_msg *)uip_appdata;
496 
497  /* print_debug("New UDP data, AODV packet type %d\n", m->type);*/
498  switch(m->type) {
499  case UAODV_RREQ_TYPE:
500  handle_incoming_rreq();
501  break;
502 
503  case UAODV_RREP_TYPE:
504  handle_incoming_rrep();
505  break;
506 
507  case UAODV_RERR_TYPE:
508  handle_incoming_rerr();
509  break;
510  }
511 
512 }
513 /*---------------------------------------------------------------------------*/
514 static enum {
515  COMMAND_NONE,
516  COMMAND_SEND_RREQ,
517  COMMAND_SEND_RERR,
518 } command;
519 
520 static uip_ipaddr_t bad_dest;
521 static u32_t bad_seqno; /* In network byte order! */
522 
523 void
524 uaodv_bad_dest(uip_ipaddr_t *dest)
525 {
526  struct uaodv_rt_entry *rt = uaodv_rt_lookup_any(dest);
527 
528  if(rt == NULL)
529  bad_seqno = 0; /* Or flag this in RERR? */
530  else {
531  rt->is_bad = 1;
532  bad_seqno = uip_htonl(rt->hseqno);
533  }
534 
535  uip_ipaddr_copy(&bad_dest, dest);
536  command = COMMAND_SEND_RERR;
537  process_post(&uaodv_process, PROCESS_EVENT_MSG, NULL);
538 }
539 
540 static uip_ipaddr_t rreq_addr;
541 static struct timer next_time;
542 
543 struct uaodv_rt_entry *
544 uaodv_request_route_to(uip_ipaddr_t *host)
545 {
546  struct uaodv_rt_entry *route = uaodv_rt_lookup(host);
547 
548  if(route != NULL) {
549  uaodv_rt_lru(route);
550  return route;
551  }
552 
553  /*
554  * Broadcast protocols must be rate-limited!
555  */
556  if(!timer_expired(&next_time)) {
557  return NULL;
558  }
559 
560  if(command != COMMAND_NONE) {
561  return NULL;
562  }
563 
564  uip_ipaddr_copy(&rreq_addr, host);
565  command = COMMAND_SEND_RREQ;
566  process_post(&uaodv_process, PROCESS_EVENT_MSG, NULL);
567  timer_set(&next_time, CLOCK_SECOND/8); /* Max 10/s per RFC3561. */
568  return NULL;
569 }
570 
571 PROCESS_THREAD(uaodv_process, ev, data)
572 {
573  PROCESS_EXITHANDLER(goto exit);
574 
575  PROCESS_BEGIN();
576 
577  printf("uaodv_process starting %lu\n", (unsigned long) my_hseqno);
578 
579  bcastconn = udp_broadcast_new(UIP_HTONS(UAODV_UDPPORT), NULL);
580  unicastconn = udp_broadcast_new(UIP_HTONS(UAODV_UDPPORT), NULL);
581 
582  while(1) {
584 
585  if(ev == tcpip_event) {
586  if(uip_newdata()) {
587  handle_incoming_packet();
588  continue;
589  }
590  if(uip_poll()) {
591  if(command == COMMAND_SEND_RREQ) {
592  if(uaodv_rt_lookup(&rreq_addr) == NULL)
593  send_rreq(&rreq_addr);
594  } else if (command == COMMAND_SEND_RERR) {
595  send_rerr(&bad_dest, &bad_seqno);
596  }
597  command = COMMAND_NONE;
598  continue;
599  }
600  }
601 
602  if(ev == PROCESS_EVENT_MSG) {
603  tcpip_poll_udp(bcastconn);
604  }
605  }
606 
607  exit:
608  command = COMMAND_NONE;
609  uaodv_rt_flush_all();
610  uip_udp_remove(bcastconn);
611  bcastconn = NULL;
612  uip_udp_remove(unicastconn);
613  unicastconn = NULL;
614  printf("uaodv_process exiting\n");
615  PROCESS_END();
616 }
617 /*---------------------------------------------------------------------------*/