Contiki 2.5
route.c
Go to the documentation of this file.
1 /**
2  * \addtogroup rimeroute
3  * @{
4  */
5 
6 /*
7  * Copyright (c) 2007, Swedish Institute of Computer Science.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the Institute nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * This file is part of the Contiki operating system.
35  *
36  * $Id: route.c,v 1.18 2010/06/15 19:22:25 adamdunkels Exp $
37  */
38 
39 /**
40  * \file
41  * Rime route table
42  * \author
43  * Adam Dunkels <adam@sics.se>
44  */
45 
46 #include <stdio.h>
47 
48 #include "lib/list.h"
49 #include "lib/memb.h"
50 #include "sys/ctimer.h"
51 #include "net/rime/route.h"
52 #include "contiki-conf.h"
53 
54 #ifdef ROUTE_CONF_ENTRIES
55 #define NUM_RT_ENTRIES ROUTE_CONF_ENTRIES
56 #else /* ROUTE_CONF_ENTRIES */
57 #define NUM_RT_ENTRIES 8
58 #endif /* ROUTE_CONF_ENTRIES */
59 
60 #ifdef ROUTE_CONF_DECAY_THRESHOLD
61 #define DECAY_THRESHOLD ROUTE_CONF_DECAY_THRESHOLD
62 #else /* ROUTE_CONF_DECAY_THRESHOLD */
63 #define DECAY_THRESHOLD 8
64 #endif /* ROUTE_CONF_DECAY_THRESHOLD */
65 
66 #ifdef ROUTE_CONF_DEFAULT_LIFETIME
67 #define DEFAULT_LIFETIME ROUTE_CONF_DEFAULT_LIFETIME
68 #else /* ROUTE_CONF_DEFAULT_LIFETIME */
69 #define DEFAULT_LIFETIME 60
70 #endif /* ROUTE_CONF_DEFAULT_LIFETIME */
71 
72 /*
73  * List of route entries.
74  */
75 LIST(route_table);
76 MEMB(route_mem, struct route_entry, NUM_RT_ENTRIES);
77 
78 static struct ctimer t;
79 
80 static int max_time = DEFAULT_LIFETIME;
81 
82 #define DEBUG 0
83 #if DEBUG
84 #include <stdio.h>
85 #define PRINTF(...) printf(__VA_ARGS__)
86 #else
87 #define PRINTF(...)
88 #endif
89 
90 
91 /*---------------------------------------------------------------------------*/
92 static void
93 periodic(void *ptr)
94 {
95  struct route_entry *e;
96 
97  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
98  e->time++;
99  if(e->time >= max_time) {
100  PRINTF("route periodic: removing entry to %d.%d with nexthop %d.%d and cost %d\n",
101  e->dest.u8[0], e->dest.u8[1],
102  e->nexthop.u8[0], e->nexthop.u8[1],
103  e->cost);
104  list_remove(route_table, e);
105  memb_free(&route_mem, e);
106  }
107  }
108 
109  ctimer_set(&t, CLOCK_SECOND, periodic, NULL);
110 }
111 /*---------------------------------------------------------------------------*/
112 void
113 route_init(void)
114 {
115  list_init(route_table);
116  memb_init(&route_mem);
117 
118  ctimer_set(&t, CLOCK_SECOND, periodic, NULL);
119 }
120 /*---------------------------------------------------------------------------*/
121 int
122 route_add(const rimeaddr_t *dest, const rimeaddr_t *nexthop,
123  uint8_t cost, uint8_t seqno)
124 {
125  struct route_entry *e;
126 
127  /* Avoid inserting duplicate entries. */
128  e = route_lookup(dest);
129  if(e != NULL && rimeaddr_cmp(&e->nexthop, nexthop)) {
130  list_remove(route_table, e);
131  } else {
132  /* Allocate a new entry or reuse the oldest entry with highest cost. */
133  e = memb_alloc(&route_mem);
134  if(e == NULL) {
135  /* Remove oldest entry. XXX */
136  e = list_chop(route_table);
137  PRINTF("route_add: removing entry to %d.%d with nexthop %d.%d and cost %d\n",
138  e->dest.u8[0], e->dest.u8[1],
139  e->nexthop.u8[0], e->nexthop.u8[1],
140  e->cost);
141  }
142  }
143 
144  rimeaddr_copy(&e->dest, dest);
145  rimeaddr_copy(&e->nexthop, nexthop);
146  e->cost = cost;
147  e->seqno = seqno;
148  e->time = 0;
149  e->decay = 0;
150 
151  /* New entry goes first. */
152  list_push(route_table, e);
153 
154  PRINTF("route_add: new entry to %d.%d with nexthop %d.%d and cost %d\n",
155  e->dest.u8[0], e->dest.u8[1],
156  e->nexthop.u8[0], e->nexthop.u8[1],
157  e->cost);
158 
159  return 0;
160 }
161 /*---------------------------------------------------------------------------*/
162 struct route_entry *
163 route_lookup(const rimeaddr_t *dest)
164 {
165  struct route_entry *e;
166  uint8_t lowest_cost;
167  struct route_entry *best_entry;
168 
169  lowest_cost = -1;
170  best_entry = NULL;
171 
172  /* Find the route with the lowest cost. */
173  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
174  /* printf("route_lookup: comparing %d.%d.%d.%d with %d.%d.%d.%d\n",
175  uip_ipaddr_to_quad(dest), uip_ipaddr_to_quad(&e->dest));*/
176 
177  if(rimeaddr_cmp(dest, &e->dest)) {
178  if(e->cost < lowest_cost) {
179  best_entry = e;
180  lowest_cost = e->cost;
181  }
182  }
183  }
184  return best_entry;
185 }
186 /*---------------------------------------------------------------------------*/
187 void
188 route_refresh(struct route_entry *e)
189 {
190  if(e != NULL) {
191  /* Refresh age of route so that used routes do not get thrown
192  out. */
193  e->time = 0;
194  e->decay = 0;
195 
196  PRINTF("route_refresh: time %d last %d decay %d for entry to %d.%d with nexthop %d.%d and cost %d\n",
197  e->time, e->time_last_decay, e->decay,
198  e->dest.u8[0], e->dest.u8[1],
199  e->nexthop.u8[0], e->nexthop.u8[1],
200  e->cost);
201 
202  }
203 }
204 /*---------------------------------------------------------------------------*/
205 void
206 route_decay(struct route_entry *e)
207 {
208  /* If routes are not refreshed, they decay over time. This function
209  is called to decay a route. The route can only be decayed once
210  per second. */
211  PRINTF("route_decay: time %d last %d decay %d for entry to %d.%d with nexthop %d.%d and cost %d\n",
212  e->time, e->time_last_decay, e->decay,
213  e->dest.u8[0], e->dest.u8[1],
214  e->nexthop.u8[0], e->nexthop.u8[1],
215  e->cost);
216 
217  if(e->time != e->time_last_decay) {
218  /* Do not decay a route too often - not more than once per second. */
219  e->time_last_decay = e->time;
220  e->decay++;
221 
222  if(e->decay >= DECAY_THRESHOLD) {
223  PRINTF("route_decay: removing entry to %d.%d with nexthop %d.%d and cost %d\n",
224  e->dest.u8[0], e->dest.u8[1],
225  e->nexthop.u8[0], e->nexthop.u8[1],
226  e->cost);
227  route_remove(e);
228  }
229  }
230 }
231 /*---------------------------------------------------------------------------*/
232 void
233 route_remove(struct route_entry *e)
234 {
235  list_remove(route_table, e);
236  memb_free(&route_mem, e);
237 }
238 /*---------------------------------------------------------------------------*/
239 void
240 route_flush_all(void)
241 {
242  struct route_entry *e;
243 
244  while(1) {
245  e = list_pop(route_table);
246  if(e != NULL) {
247  memb_free(&route_mem, e);
248  } else {
249  break;
250  }
251  }
252 }
253 /*---------------------------------------------------------------------------*/
254 void
255 route_set_lifetime(int seconds)
256 {
257  max_time = seconds;
258 }
259 /*---------------------------------------------------------------------------*/
260 int
261 route_num(void)
262 {
263  struct route_entry *e;
264  int i = 0;
265 
266  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
267  i++;
268  }
269  return i;
270 }
271 /*---------------------------------------------------------------------------*/
272 struct route_entry *
273 route_get(int num)
274 {
275  struct route_entry *e;
276  int i = 0;
277 
278  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
279  if(i == num) {
280  return e;
281  }
282  i++;
283  }
284  return NULL;
285 }
286 /*---------------------------------------------------------------------------*/
287 /** @} */