Contiki 3.x
route.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007, 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  */
32 
33 /**
34  * \file
35  * Rime route table
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  */
39 
40 /**
41  * \addtogroup rimeroute
42  * @{
43  */
44 
45 #include <stdio.h>
46 
47 #include "lib/list.h"
48 #include "lib/memb.h"
49 #include "sys/ctimer.h"
50 #include "net/rime/route.h"
51 #include "contiki-conf.h"
52 
53 #ifdef ROUTE_CONF_ENTRIES
54 #define NUM_RT_ENTRIES ROUTE_CONF_ENTRIES
55 #else /* ROUTE_CONF_ENTRIES */
56 #define NUM_RT_ENTRIES 8
57 #endif /* ROUTE_CONF_ENTRIES */
58 
59 #ifdef ROUTE_CONF_DECAY_THRESHOLD
60 #define DECAY_THRESHOLD ROUTE_CONF_DECAY_THRESHOLD
61 #else /* ROUTE_CONF_DECAY_THRESHOLD */
62 #define DECAY_THRESHOLD 8
63 #endif /* ROUTE_CONF_DECAY_THRESHOLD */
64 
65 #ifdef ROUTE_CONF_DEFAULT_LIFETIME
66 #define DEFAULT_LIFETIME ROUTE_CONF_DEFAULT_LIFETIME
67 #else /* ROUTE_CONF_DEFAULT_LIFETIME */
68 #define DEFAULT_LIFETIME 60
69 #endif /* ROUTE_CONF_DEFAULT_LIFETIME */
70 
71 /*
72  * List of route entries.
73  */
74 LIST(route_table);
75 MEMB(route_mem, struct route_entry, NUM_RT_ENTRIES);
76 
77 static struct ctimer t;
78 
79 static int max_time = DEFAULT_LIFETIME;
80 
81 #define DEBUG 0
82 #if DEBUG
83 #include <stdio.h>
84 #define PRINTF(...) printf(__VA_ARGS__)
85 #else
86 #define PRINTF(...)
87 #endif
88 
89 
90 /*---------------------------------------------------------------------------*/
91 static void
92 periodic(void *ptr)
93 {
94  struct route_entry *e;
95 
96  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
97  e->time++;
98  if(e->time >= max_time) {
99  PRINTF("route periodic: removing entry to %d.%d with nexthop %d.%d and cost %d\n",
100  e->dest.u8[0], e->dest.u8[1],
101  e->nexthop.u8[0], e->nexthop.u8[1],
102  e->cost);
103  list_remove(route_table, e);
104  memb_free(&route_mem, e);
105  }
106  }
107 
108  ctimer_set(&t, CLOCK_SECOND, periodic, NULL);
109 }
110 /*---------------------------------------------------------------------------*/
111 void
112 route_init(void)
113 {
114  list_init(route_table);
115  memb_init(&route_mem);
116 
117  ctimer_set(&t, CLOCK_SECOND, periodic, NULL);
118 }
119 /*---------------------------------------------------------------------------*/
120 int
121 route_add(const linkaddr_t *dest, const linkaddr_t *nexthop,
122  uint8_t cost, uint8_t seqno)
123 {
124  struct route_entry *e, *oldest = NULL;
125 
126  /* Avoid inserting duplicate entries. */
127  e = route_lookup(dest);
128  if(e != NULL && linkaddr_cmp(&e->nexthop, nexthop)) {
129  list_remove(route_table, e);
130  } else {
131  /* Allocate a new entry or reuse the oldest entry with highest cost. */
132  e = memb_alloc(&route_mem);
133  if(e == NULL) {
134  /* Remove oldest entry. */
135  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
136  if(oldest == NULL || e->time >= oldest->time) {
137  oldest = e;
138  }
139  }
140  e = oldest;
141  list_remove(route_table, e);
142  PRINTF("route_add: removing entry to %d.%d with nexthop %d.%d and cost %d\n",
143  e->dest.u8[0], e->dest.u8[1],
144  e->nexthop.u8[0], e->nexthop.u8[1],
145  e->cost);
146  }
147  }
148 
149  linkaddr_copy(&e->dest, dest);
150  linkaddr_copy(&e->nexthop, nexthop);
151  e->cost = cost;
152  e->seqno = seqno;
153  e->time = 0;
154  e->decay = 0;
155 
156  /* New entry goes first. */
157  list_push(route_table, e);
158 
159  PRINTF("route_add: new entry to %d.%d with nexthop %d.%d and cost %d\n",
160  e->dest.u8[0], e->dest.u8[1],
161  e->nexthop.u8[0], e->nexthop.u8[1],
162  e->cost);
163 
164  return 0;
165 }
166 /*---------------------------------------------------------------------------*/
167 struct route_entry *
168 route_lookup(const linkaddr_t *dest)
169 {
170  struct route_entry *e;
171  uint8_t lowest_cost;
172  struct route_entry *best_entry;
173 
174  lowest_cost = -1;
175  best_entry = NULL;
176 
177  /* Find the route with the lowest cost. */
178  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
179  /* printf("route_lookup: comparing %d.%d.%d.%d with %d.%d.%d.%d\n",
180  uip_ipaddr_to_quad(dest), uip_ipaddr_to_quad(&e->dest));*/
181 
182  if(linkaddr_cmp(dest, &e->dest)) {
183  if(e->cost < lowest_cost) {
184  best_entry = e;
185  lowest_cost = e->cost;
186  }
187  }
188  }
189  return best_entry;
190 }
191 /*---------------------------------------------------------------------------*/
192 void
193 route_refresh(struct route_entry *e)
194 {
195  if(e != NULL) {
196  /* Refresh age of route so that used routes do not get thrown
197  out. */
198  e->time = 0;
199  e->decay = 0;
200 
201  PRINTF("route_refresh: time %d last %d decay %d for entry to %d.%d with nexthop %d.%d and cost %d\n",
202  e->time, e->time_last_decay, e->decay,
203  e->dest.u8[0], e->dest.u8[1],
204  e->nexthop.u8[0], e->nexthop.u8[1],
205  e->cost);
206 
207  }
208 }
209 /*---------------------------------------------------------------------------*/
210 void
211 route_decay(struct route_entry *e)
212 {
213  /* If routes are not refreshed, they decay over time. This function
214  is called to decay a route. The route can only be decayed once
215  per second. */
216  PRINTF("route_decay: time %d last %d decay %d for entry to %d.%d with nexthop %d.%d and cost %d\n",
217  e->time, e->time_last_decay, e->decay,
218  e->dest.u8[0], e->dest.u8[1],
219  e->nexthop.u8[0], e->nexthop.u8[1],
220  e->cost);
221 
222  if(e->time != e->time_last_decay) {
223  /* Do not decay a route too often - not more than once per second. */
224  e->time_last_decay = e->time;
225  e->decay++;
226 
227  if(e->decay >= DECAY_THRESHOLD) {
228  PRINTF("route_decay: removing entry to %d.%d with nexthop %d.%d and cost %d\n",
229  e->dest.u8[0], e->dest.u8[1],
230  e->nexthop.u8[0], e->nexthop.u8[1],
231  e->cost);
232  route_remove(e);
233  }
234  }
235 }
236 /*---------------------------------------------------------------------------*/
237 void
238 route_remove(struct route_entry *e)
239 {
240  list_remove(route_table, e);
241  memb_free(&route_mem, e);
242 }
243 /*---------------------------------------------------------------------------*/
244 void
245 route_flush_all(void)
246 {
247  struct route_entry *e;
248 
249  while(1) {
250  e = list_pop(route_table);
251  if(e != NULL) {
252  memb_free(&route_mem, e);
253  } else {
254  break;
255  }
256  }
257 }
258 /*---------------------------------------------------------------------------*/
259 void
260 route_set_lifetime(int seconds)
261 {
262  max_time = seconds;
263 }
264 /*---------------------------------------------------------------------------*/
265 int
266 route_num(void)
267 {
268  struct route_entry *e;
269  int i = 0;
270 
271  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
272  i++;
273  }
274  return i;
275 }
276 /*---------------------------------------------------------------------------*/
277 struct route_entry *
278 route_get(int num)
279 {
280  struct route_entry *e;
281  int i = 0;
282 
283  for(e = list_head(route_table); e != NULL; e = list_item_next(e)) {
284  if(i == num) {
285  return e;
286  }
287  i++;
288  }
289  return NULL;
290 }
291 /*---------------------------------------------------------------------------*/
292 /** @} */
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:240
#define LIST(name)
Declare a linked list.
Definition: list.h:86
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:89
void * list_pop(list_t list)
Remove the first object on a list.
Definition: list.c:218
void * list_item_next(void *item)
Get the next item following this item.
Definition: list.c:325
void list_init(list_t list)
Initialize a list.
Definition: list.c:66
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition: memb.c:52
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:83
Header file for the callback timer
#define NULL
The null pointer.
Header file for the Rime route table
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
Linked list manipulation routines.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
Memory block allocation routines.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two Rime addresses.
Definition: linkaddr.c:66
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
Definition: linkaddr.c:60
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:79
void list_push(list_t list, void *item)
Add an item to the start of the list.
Definition: list.c:165