Contiki 3.x
uip-ds6-route.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
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  *
14  * 3. Neither the name of the copyright holder nor the names of its
15  * contributors may be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 /**
33  * \addtogroup uip6
34  * @{
35  */
36 
37 /**
38  * \file
39  * Routing table manipulation
40  */
41 #include "net/ipv6/uip-ds6.h"
42 #include "net/ip/uip.h"
43 
44 #include "lib/list.h"
45 #include "lib/memb.h"
46 #include "net/nbr-table.h"
47 
48 #include <string.h>
49 
50 /* A configurable function called after adding a new neighbor as next hop */
51 #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
52 void NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK(const linkaddr_t *addr);
53 #endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK */
54 
55 /* A configurable function called after removing a next hop neighbor */
56 #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
57 void NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(const linkaddr_t *addr);
58 #endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK */
59 
60 #if (UIP_CONF_MAX_ROUTES != 0)
61 /* The nbr_routes holds a neighbor table to be able to maintain
62  information about what routes go through what neighbor. This
63  neighbor table is registered with the central nbr-table repository
64  so that it will be maintained along with the rest of the neighbor
65  tables in the system. */
66 NBR_TABLE_GLOBAL(struct uip_ds6_route_neighbor_routes, nbr_routes);
67 MEMB(neighborroutememb, struct uip_ds6_route_neighbor_route, UIP_DS6_ROUTE_NB);
68 
69 /* Each route is repressented by a uip_ds6_route_t structure and
70  memory for each route is allocated from the routememb memory
71  block. These routes are maintained on the routelist. */
72 LIST(routelist);
73 MEMB(routememb, uip_ds6_route_t, UIP_DS6_ROUTE_NB);
74 
75 static int num_routes = 0;
76 static void rm_routelist_callback(nbr_table_item_t *ptr);
77 
78 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
79 
80 /* Default routes are held on the defaultrouterlist and their
81  structures are allocated from the defaultroutermemb memory block.*/
82 LIST(defaultrouterlist);
83 MEMB(defaultroutermemb, uip_ds6_defrt_t, UIP_DS6_DEFRT_NB);
84 
85 #if UIP_DS6_NOTIFICATIONS
86 LIST(notificationlist);
87 #endif
88 
89 #undef DEBUG
90 #define DEBUG DEBUG_NONE
91 #include "net/ip/uip-debug.h"
92 
93 /*---------------------------------------------------------------------------*/
94 #if DEBUG != DEBUG_NONE
95 static void
96 assert_nbr_routes_list_sane(void)
97 {
98  uip_ds6_route_t *r;
99  int count;
100 
101  /* Check if the route list has an infinite loop. */
102  for(r = uip_ds6_route_head(),
103  count = 0;
104  r != NULL &&
105  count < UIP_DS6_ROUTE_NB * 2;
106  r = uip_ds6_route_next(r),
107  count++);
108 
109  if(count > UIP_DS6_ROUTE_NB) {
110  printf("uip-ds6-route.c: assert_nbr_routes_list_sane route list is in infinite loop\n");
111  }
112 
113  /* Make sure that the route list has as many entries as the
114  num_routes vairable. */
115  if(count < num_routes) {
116  printf("uip-ds6-route.c: assert_nbr_routes_list_sane too few entries on route list: should be %d, is %d, max %d\n",
117  num_routes, count, UIP_CONF_MAX_ROUTES);
118  }
119 }
120 #endif /* DEBUG != DEBUG_NONE */
121 /*---------------------------------------------------------------------------*/
122 #if UIP_DS6_NOTIFICATIONS
123 static void
124 call_route_callback(int event, uip_ipaddr_t *route,
125  uip_ipaddr_t *nexthop)
126 {
127  int num;
128  struct uip_ds6_notification *n;
129  for(n = list_head(notificationlist);
130  n != NULL;
131  n = list_item_next(n)) {
132  if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD ||
133  event == UIP_DS6_NOTIFICATION_DEFRT_RM) {
134  num = list_length(defaultrouterlist);
135  } else {
136  num = num_routes;
137  }
138  n->callback(event, route, nexthop, num);
139  }
140 }
141 /*---------------------------------------------------------------------------*/
142 void
143 uip_ds6_notification_add(struct uip_ds6_notification *n,
144  uip_ds6_notification_callback c)
145 {
146  if(n != NULL && c != NULL) {
147  n->callback = c;
148  list_add(notificationlist, n);
149  }
150 }
151 /*---------------------------------------------------------------------------*/
152 void
153 uip_ds6_notification_rm(struct uip_ds6_notification *n)
154 {
155  list_remove(notificationlist, n);
156 }
157 #endif
158 /*---------------------------------------------------------------------------*/
159 void
160 uip_ds6_route_init(void)
161 {
162 #if (UIP_CONF_MAX_ROUTES != 0)
163  memb_init(&routememb);
164  list_init(routelist);
165  nbr_table_register(nbr_routes,
166  (nbr_table_callback *)rm_routelist_callback);
167 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
168 
169  memb_init(&defaultroutermemb);
170  list_init(defaultrouterlist);
171 
172 #if UIP_DS6_NOTIFICATIONS
173  list_init(notificationlist);
174 #endif
175 }
176 #if (UIP_CONF_MAX_ROUTES != 0)
177 /*---------------------------------------------------------------------------*/
178 static uip_lladdr_t *
179 uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route)
180 {
181  if(route != NULL) {
182  return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes,
183  route->neighbor_routes);
184  } else {
185  return NULL;
186  }
187 }
188 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
189 /*---------------------------------------------------------------------------*/
190 uip_ipaddr_t *
191 uip_ds6_route_nexthop(uip_ds6_route_t *route)
192 {
193 #if (UIP_CONF_MAX_ROUTES != 0)
194  if(route != NULL) {
195  return uip_ds6_nbr_ipaddr_from_lladdr(uip_ds6_route_nexthop_lladdr(route));
196  } else {
197  return NULL;
198  }
199 #else /* (UIP_CONF_MAX_ROUTES != 0) */
200  return NULL;
201 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
202 }
203 /*---------------------------------------------------------------------------*/
205 uip_ds6_route_head(void)
206 {
207 #if (UIP_CONF_MAX_ROUTES != 0)
208  return list_head(routelist);
209 #else /* (UIP_CONF_MAX_ROUTES != 0) */
210  return NULL;
211 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
212 }
213 /*---------------------------------------------------------------------------*/
215 uip_ds6_route_next(uip_ds6_route_t *r)
216 {
217 #if (UIP_CONF_MAX_ROUTES != 0)
218  if(r != NULL) {
220  return n;
221  }
222 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
223  return NULL;
224 }
225 /*---------------------------------------------------------------------------*/
226 int
227 uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr)
228 {
229 #if (UIP_CONF_MAX_ROUTES != 0)
230  const uip_lladdr_t *lladdr;
231  lladdr = uip_ds6_nbr_lladdr_from_ipaddr(ipaddr);
232 
233  if(lladdr == NULL) {
234  return 0;
235  }
236 
237  return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL;
238 #else /* (UIP_CONF_MAX_ROUTES != 0) */
239  return 0;
240 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
241 }
242 /*---------------------------------------------------------------------------*/
243 int
244 uip_ds6_route_num_routes(void)
245 {
246 #if (UIP_CONF_MAX_ROUTES != 0)
247  return num_routes;
248 #else /* (UIP_CONF_MAX_ROUTES != 0) */
249  return 0;
250 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
251 }
252 /*---------------------------------------------------------------------------*/
254 uip_ds6_route_lookup(uip_ipaddr_t *addr)
255 {
256 #if (UIP_CONF_MAX_ROUTES != 0)
257  uip_ds6_route_t *r;
258  uip_ds6_route_t *found_route;
259  uint8_t longestmatch;
260 
261  PRINTF("uip-ds6-route: Looking up route for ");
262  PRINT6ADDR(addr);
263  PRINTF("\n");
264 
265 
266  found_route = NULL;
267  longestmatch = 0;
268  for(r = uip_ds6_route_head();
269  r != NULL;
270  r = uip_ds6_route_next(r)) {
271  if(r->length >= longestmatch &&
272  uip_ipaddr_prefixcmp(addr, &r->ipaddr, r->length)) {
273  longestmatch = r->length;
274  found_route = r;
275  /* check if total match - e.g. all 128 bits do match */
276  if(longestmatch == 128) {
277  break;
278  }
279  }
280  }
281 
282  if(found_route != NULL) {
283  PRINTF("uip-ds6-route: Found route: ");
284  PRINT6ADDR(addr);
285  PRINTF(" via ");
286  PRINT6ADDR(uip_ds6_route_nexthop(found_route));
287  PRINTF("\n");
288  } else {
289  PRINTF("uip-ds6-route: No route found\n");
290  }
291 
292  if(found_route != NULL && found_route != list_head(routelist)) {
293  /* If we found a route, we put it at the start of the routeslist
294  list. The list is ordered by how recently we looked them up:
295  the least recently used route will be at the end of the
296  list - for fast lookups (assuming multiple packets to the same node). */
297 
298  list_remove(routelist, found_route);
299  list_push(routelist, found_route);
300  }
301 
302  return found_route;
303 #else /* (UIP_CONF_MAX_ROUTES != 0) */
304  return NULL;
305 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
306 }
307 /*---------------------------------------------------------------------------*/
309 uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
310  uip_ipaddr_t *nexthop)
311 {
312 #if (UIP_CONF_MAX_ROUTES != 0)
313  uip_ds6_route_t *r;
314  struct uip_ds6_route_neighbor_route *nbrr;
315 
316 #if DEBUG != DEBUG_NONE
317  assert_nbr_routes_list_sane();
318 #endif /* DEBUG != DEBUG_NONE */
319 
320  /* Get link-layer address of next hop, make sure it is in neighbor table */
321  const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
322  if(nexthop_lladdr == NULL) {
323  PRINTF("uip_ds6_route_add: neighbor link-local address unknown for ");
324  PRINT6ADDR(nexthop);
325  PRINTF("\n");
326  return NULL;
327  }
328 
329  /* First make sure that we don't add a route twice. If we find an
330  existing route for our destination, we'll delete the old
331  one first. */
332  r = uip_ds6_route_lookup(ipaddr);
333  if(r != NULL) {
334  uip_ipaddr_t *current_nexthop;
335  current_nexthop = uip_ds6_route_nexthop(r);
336  if(current_nexthop != NULL && uip_ipaddr_cmp(nexthop, current_nexthop)) {
337  /* no need to update route - already correct! */
338  return r;
339  }
340  PRINTF("uip_ds6_route_add: old route for ");
341  PRINT6ADDR(ipaddr);
342  PRINTF(" found, deleting it\n");
343 
344  uip_ds6_route_rm(r);
345  }
346  {
347  struct uip_ds6_route_neighbor_routes *routes;
348  /* If there is no routing entry, create one. We first need to
349  check if we have room for this route. If not, we remove the
350  least recently used one we have. */
351 
352  if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) {
353  uip_ds6_route_t *oldest;
354  oldest = NULL;
355 #if UIP_DS6_ROUTE_REMOVE_LEAST_RECENTLY_USED
356  /* Removing the oldest route entry from the route table. The
357  least recently used route is the first route on the list. */
358  oldest = list_tail(routelist);
359 #endif
360  if(oldest == NULL) {
361  return NULL;
362  }
363  PRINTF("uip_ds6_route_add: dropping route to ");
364  PRINT6ADDR(&oldest->ipaddr);
365  PRINTF("\n");
366  uip_ds6_route_rm(oldest);
367  }
368 
369 
370  /* Every neighbor on our neighbor table holds a struct
371  uip_ds6_route_neighbor_routes which holds a list of routes that
372  go through the neighbor. We add our route entry to this list.
373 
374  We first check to see if we already have this neighbor in our
375  nbr_route table. If so, the neighbor already has a route entry
376  list.
377  */
378  routes = nbr_table_get_from_lladdr(nbr_routes,
379  (linkaddr_t *)nexthop_lladdr);
380 
381  if(routes == NULL) {
382  /* If the neighbor did not have an entry in our neighbor table,
383  we create one. The nbr_table_add_lladdr() function returns a
384  pointer to a pointer that we may use for our own purposes. We
385  initialize this pointer with the list of routing entries that
386  are attached to this neighbor. */
387  routes = nbr_table_add_lladdr(nbr_routes,
388  (linkaddr_t *)nexthop_lladdr,
389  NBR_TABLE_REASON_ROUTE, NULL);
390  if(routes == NULL) {
391  /* This should not happen, as we explicitly deallocated one
392  route table entry above. */
393  PRINTF("uip_ds6_route_add: could not allocate neighbor table entry\n");
394  return NULL;
395  }
396  LIST_STRUCT_INIT(routes, route_list);
397 #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
398  NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK((const linkaddr_t *)nexthop_lladdr);
399 #endif
400  }
401 
402  /* Allocate a routing entry and populate it. */
403  r = memb_alloc(&routememb);
404 
405  if(r == NULL) {
406  /* This should not happen, as we explicitly deallocated one
407  route table entry above. */
408  PRINTF("uip_ds6_route_add: could not allocate route\n");
409  return NULL;
410  }
411 
412  /* add new routes first - assuming that there is a reason to add this
413  and that there is a packet coming soon. */
414  list_push(routelist, r);
415 
416  nbrr = memb_alloc(&neighborroutememb);
417  if(nbrr == NULL) {
418  /* This should not happen, as we explicitly deallocated one
419  route table entry above. */
420  PRINTF("uip_ds6_route_add: could not allocate neighbor route list entry\n");
421  memb_free(&routememb, r);
422  return NULL;
423  }
424 
425  nbrr->route = r;
426  /* Add the route to this neighbor */
427  list_add(routes->route_list, nbrr);
428  r->neighbor_routes = routes;
429  num_routes++;
430 
431  PRINTF("uip_ds6_route_add num %d\n", num_routes);
432 
433  /* lock this entry so that nexthop is not removed */
434  nbr_table_lock(nbr_routes, routes);
435  }
436 
437  uip_ipaddr_copy(&(r->ipaddr), ipaddr);
438  r->length = length;
439 
440 #ifdef UIP_DS6_ROUTE_STATE_TYPE
441  memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE));
442 #endif
443 
444  PRINTF("uip_ds6_route_add: adding route: ");
445  PRINT6ADDR(ipaddr);
446  PRINTF(" via ");
447  PRINT6ADDR(nexthop);
448  PRINTF("\n");
449  ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
450 
451 #if UIP_DS6_NOTIFICATIONS
452  call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop);
453 #endif
454 
455 #if DEBUG != DEBUG_NONE
456  assert_nbr_routes_list_sane();
457 #endif /* DEBUG != DEBUG_NONE */
458  return r;
459 
460 #else /* (UIP_CONF_MAX_ROUTES != 0) */
461  return NULL;
462 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
463 }
464 
465 /*---------------------------------------------------------------------------*/
466 void
467 uip_ds6_route_rm(uip_ds6_route_t *route)
468 {
469 #if (UIP_CONF_MAX_ROUTES != 0)
470  struct uip_ds6_route_neighbor_route *neighbor_route;
471 #if DEBUG != DEBUG_NONE
472  assert_nbr_routes_list_sane();
473 #endif /* DEBUG != DEBUG_NONE */
474  if(route != NULL && route->neighbor_routes != NULL) {
475 
476  PRINTF("uip_ds6_route_rm: removing route: ");
477  PRINT6ADDR(&route->ipaddr);
478  PRINTF("\n");
479 
480  /* Remove the route from the route list */
481  list_remove(routelist, route);
482 
483  /* Find the corresponding neighbor_route and remove it. */
484  for(neighbor_route = list_head(route->neighbor_routes->route_list);
485  neighbor_route != NULL && neighbor_route->route != route;
486  neighbor_route = list_item_next(neighbor_route));
487 
488  if(neighbor_route == NULL) {
489  PRINTF("uip_ds6_route_rm: neighbor_route was NULL for ");
490  uip_debug_ipaddr_print(&route->ipaddr);
491  PRINTF("\n");
492  }
493  list_remove(route->neighbor_routes->route_list, neighbor_route);
494  if(list_head(route->neighbor_routes->route_list) == NULL) {
495  /* If this was the only route using this neighbor, remove the
496  neighbor from the table - this implicitly unlocks nexthop */
497 #if (DEBUG) & DEBUG_ANNOTATE
498  uip_ipaddr_t *nexthop = uip_ds6_route_nexthop(route);
499  if(nexthop != NULL) {
500  ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
501  }
502 #endif /* (DEBUG) & DEBUG_ANNOTATE */
503  PRINTF("uip_ds6_route_rm: removing neighbor too\n");
504  nbr_table_remove(nbr_routes, route->neighbor_routes->route_list);
505 #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
506  NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(
507  (const linkaddr_t *)nbr_table_get_lladdr(nbr_routes, route->neighbor_routes->route_list));
508 #endif
509  }
510  memb_free(&routememb, route);
511  memb_free(&neighborroutememb, neighbor_route);
512 
513  num_routes--;
514 
515  PRINTF("uip_ds6_route_rm num %d\n", num_routes);
516 
517 #if UIP_DS6_NOTIFICATIONS
518  call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
519  &route->ipaddr, uip_ds6_route_nexthop(route));
520 #endif
521  }
522 
523 #if DEBUG != DEBUG_NONE
524  assert_nbr_routes_list_sane();
525 #endif /* DEBUG != DEBUG_NONE */
526 
527 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
528  return;
529 }
530 #if (UIP_CONF_MAX_ROUTES != 0)
531 /*---------------------------------------------------------------------------*/
532 static void
533 rm_routelist(struct uip_ds6_route_neighbor_routes *routes)
534 {
535 #if DEBUG != DEBUG_NONE
536  assert_nbr_routes_list_sane();
537 #endif /* DEBUG != DEBUG_NONE */
538  PRINTF("uip_ds6_route_rm_routelist\n");
539  if(routes != NULL && routes->route_list != NULL) {
541  r = list_head(routes->route_list);
542  while(r != NULL) {
543  uip_ds6_route_rm(r->route);
544  r = list_head(routes->route_list);
545  }
546  nbr_table_remove(nbr_routes, routes);
547  }
548 #if DEBUG != DEBUG_NONE
549  assert_nbr_routes_list_sane();
550 #endif /* DEBUG != DEBUG_NONE */
551 }
552 /*---------------------------------------------------------------------------*/
553 static void
554 rm_routelist_callback(nbr_table_item_t *ptr)
555 {
556  rm_routelist((struct uip_ds6_route_neighbor_routes *)ptr);
557 }
558 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
559 /*---------------------------------------------------------------------------*/
560 void
561 uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop)
562 {
563 #if (UIP_CONF_MAX_ROUTES != 0)
564  /* Get routing entry list of this neighbor */
565  const uip_lladdr_t *nexthop_lladdr;
566  struct uip_ds6_route_neighbor_routes *routes;
567 
568  nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
569  routes = nbr_table_get_from_lladdr(nbr_routes,
570  (linkaddr_t *)nexthop_lladdr);
571  rm_routelist(routes);
572 #endif /* (UIP_CONF_MAX_ROUTES != 0) */
573 }
574 /*---------------------------------------------------------------------------*/
576 uip_ds6_defrt_add(uip_ipaddr_t *ipaddr, unsigned long interval)
577 {
578  uip_ds6_defrt_t *d;
579 
580 #if DEBUG != DEBUG_NONE
581  assert_nbr_routes_list_sane();
582 #endif /* DEBUG != DEBUG_NONE */
583 
584  PRINTF("uip_ds6_defrt_add\n");
585  d = uip_ds6_defrt_lookup(ipaddr);
586  if(d == NULL) {
587  d = memb_alloc(&defaultroutermemb);
588  if(d == NULL) {
589  PRINTF("uip_ds6_defrt_add: could not add default route to ");
590  PRINT6ADDR(ipaddr);
591  PRINTF(", out of memory\n");
592  return NULL;
593  } else {
594  PRINTF("uip_ds6_defrt_add: adding default route to ");
595  PRINT6ADDR(ipaddr);
596  PRINTF("\n");
597  }
598 
599  list_push(defaultrouterlist, d);
600  }
601 
602  uip_ipaddr_copy(&d->ipaddr, ipaddr);
603  if(interval != 0) {
604  stimer_set(&d->lifetime, interval);
605  d->isinfinite = 0;
606  } else {
607  d->isinfinite = 1;
608  }
609 
610  ANNOTATE("#L %u 1\n", ipaddr->u8[sizeof(uip_ipaddr_t) - 1]);
611 
612 #if UIP_DS6_NOTIFICATIONS
613  call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr);
614 #endif
615 
616 #if DEBUG != DEBUG_NONE
617  assert_nbr_routes_list_sane();
618 #endif /* DEBUG != DEBUG_NONE */
619 
620  return d;
621 }
622 /*---------------------------------------------------------------------------*/
623 void
624 uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt)
625 {
626  uip_ds6_defrt_t *d;
627 
628 #if DEBUG != DEBUG_NONE
629  assert_nbr_routes_list_sane();
630 #endif /* DEBUG != DEBUG_NONE */
631 
632  /* Make sure that the defrt is in the list before we remove it. */
633  for(d = list_head(defaultrouterlist);
634  d != NULL;
635  d = list_item_next(d)) {
636  if(d == defrt) {
637  PRINTF("Removing default route\n");
638  list_remove(defaultrouterlist, defrt);
639  memb_free(&defaultroutermemb, defrt);
640  ANNOTATE("#L %u 0\n", defrt->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]);
641 #if UIP_DS6_NOTIFICATIONS
642  call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_RM,
643  &defrt->ipaddr, &defrt->ipaddr);
644 #endif
645  return;
646  }
647  }
648 #if DEBUG != DEBUG_NONE
649  assert_nbr_routes_list_sane();
650 #endif /* DEBUG != DEBUG_NONE */
651 
652 }
653 /*---------------------------------------------------------------------------*/
655 uip_ds6_defrt_lookup(uip_ipaddr_t *ipaddr)
656 {
657  uip_ds6_defrt_t *d;
658  for(d = list_head(defaultrouterlist);
659  d != NULL;
660  d = list_item_next(d)) {
661  if(uip_ipaddr_cmp(&d->ipaddr, ipaddr)) {
662  return d;
663  }
664  }
665  return NULL;
666 }
667 /*---------------------------------------------------------------------------*/
668 uip_ipaddr_t *
669 uip_ds6_defrt_choose(void)
670 {
671  uip_ds6_defrt_t *d;
672  uip_ds6_nbr_t *bestnbr;
673  uip_ipaddr_t *addr;
674 
675  addr = NULL;
676  for(d = list_head(defaultrouterlist);
677  d != NULL;
678  d = list_item_next(d)) {
679  PRINTF("Defrt, IP address ");
680  PRINT6ADDR(&d->ipaddr);
681  PRINTF("\n");
682  bestnbr = uip_ds6_nbr_lookup(&d->ipaddr);
683  if(bestnbr != NULL && bestnbr->state != NBR_INCOMPLETE) {
684  PRINTF("Defrt found, IP address ");
685  PRINT6ADDR(&d->ipaddr);
686  PRINTF("\n");
687  return &d->ipaddr;
688  } else {
689  addr = &d->ipaddr;
690  PRINTF("Defrt INCOMPLETE found, IP address ");
691  PRINT6ADDR(&d->ipaddr);
692  PRINTF("\n");
693  }
694  }
695  return addr;
696 }
697 /*---------------------------------------------------------------------------*/
698 void
699 uip_ds6_defrt_periodic(void)
700 {
701  uip_ds6_defrt_t *d;
702  d = list_head(defaultrouterlist);
703  while(d != NULL) {
704  if(!d->isinfinite &&
705  stimer_expired(&d->lifetime)) {
706  PRINTF("uip_ds6_defrt_periodic: defrt lifetime expired\n");
707  uip_ds6_defrt_rm(d);
708  d = list_head(defaultrouterlist);
709  } else {
710  d = list_item_next(d);
711  }
712  }
713 }
714 /*---------------------------------------------------------------------------*/
715 /** @} */
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:129
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
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
A neighbor route list entry, used on the uip_ds6_route->neighbor_routes->route_list list...
Header file for IPv6-related data structures.
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:89
int stimer_expired(struct stimer *t)
Check if a timer has expired.
Definition: stimer.c:124
void * list_item_next(void *item)
Get the next item following this item.
Definition: list.c:325
#define UIP_DS6_ROUTE_STATE_TYPE
define some additional RPL related route state and neighbor callback for RPL - if not a DS6_ROUTE_STA...
Definition: uip-ds6-route.h:98
An entry in the default router list.
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
Definition: uip-ds6-nbr.h:61
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1027
static uip_ds6_defrt_t * defrt
Pointer to a nbr cache entry.
Definition: uip-nd6.c:123
An entry in the nbr cache.
Definition: uip-ds6-nbr.h:70
static uip_ds6_route_t * route
The next route to use.
Definition: res_routes.c:31
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
#define NULL
The null pointer.
802.3 address
Definition: uip.h:129
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition: stimer.c:67
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:143
Linked list manipulation routines.
static volatile clock_time_t count
These routines define the AVR-specific calls declared in /core/sys/clock.h CLOCK_SECOND is the number...
Definition: clock.c:80
Header file for the uIP TCP/IP stack.
void * list_tail(list_t list)
Get the tail of a list.
Definition: list.c:118
Memory block allocation routines.
A set of debugging macros for the IP stack
int list_length(list_t list)
Get the length of a list.
Definition: list.c:275
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
Definition: list.h:122
The neighbor routes hold a list of routing table entries that are attached to a specific neihbor...
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
An entry in the routing table.
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