Contiki-NG
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 uip
34 * @{
35 */
36
37/**
38 * \file
39 * Routing table manipulation
40 */
41#include "net/ipv6/uip-ds6.h"
43#include "net/ipv6/uip.h"
44
45#include "lib/list.h"
46#include "lib/memb.h"
47#include "net/nbr-table.h"
48
49/* Log configuration */
50#include "sys/log.h"
51#define LOG_MODULE "IPv6 Route"
52#define LOG_LEVEL LOG_LEVEL_IPV6
53
54#if BUILD_WITH_ORCHESTRA
55
56#ifndef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
57#define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added
58#endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK */
59
60#ifndef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
61#define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed
62#endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK */
63
64#endif /* BUILD_WITH_ORCHESTRA */
65
66/* A configurable function called after adding a new neighbor as next hop */
67#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
68void NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK(const linkaddr_t *addr);
69#endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK */
70
71/* A configurable function called after removing a next hop neighbor */
72#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
73void NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(const linkaddr_t *addr);
74#endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK */
75
76#if (UIP_MAX_ROUTES != 0)
77/* The nbr_routes holds a neighbor table to be able to maintain
78 information about what routes go through what neighbor. This
79 neighbor table is registered with the central nbr-table repository
80 so that it will be maintained along with the rest of the neighbor
81 tables in the system. */
82NBR_TABLE_GLOBAL(struct uip_ds6_route_neighbor_routes, nbr_routes);
83MEMB(neighborroutememb, struct uip_ds6_route_neighbor_route, UIP_DS6_ROUTE_NB);
84
85/* Each route is repressented by a uip_ds6_route_t structure and
86 memory for each route is allocated from the routememb memory
87 block. These routes are maintained on the routelist. */
88LIST(routelist);
89MEMB(routememb, uip_ds6_route_t, UIP_DS6_ROUTE_NB);
90
91static int num_routes = 0;
92static void rm_routelist_callback(nbr_table_item_t *ptr);
93
94#endif /* (UIP_MAX_ROUTES != 0) */
95
96/* Default routes are held on the defaultrouterlist and their
97 structures are allocated from the defaultroutermemb memory block.*/
98LIST(defaultrouterlist);
99MEMB(defaultroutermemb, uip_ds6_defrt_t, UIP_DS6_DEFRT_NB);
100
101#if UIP_DS6_NOTIFICATIONS
102LIST(notificationlist);
103#endif
104
105/*---------------------------------------------------------------------------*/
106static void
107assert_nbr_routes_list_sane(void)
108{
110 int count;
111
112 /* Check if the route list has an infinite loop. */
113 for(r = uip_ds6_route_head(),
114 count = 0;
115 r != NULL &&
116 count < UIP_DS6_ROUTE_NB * 2;
117 r = uip_ds6_route_next(r),
118 count++);
119
120 if(count > UIP_DS6_ROUTE_NB) {
121 printf("uip-ds6-route.c: assert_nbr_routes_list_sane route list is in infinite loop\n");
122 }
123
124#if (UIP_MAX_ROUTES != 0)
125 /* Make sure that the route list has as many entries as the
126 num_routes vairable. */
127 if(count < num_routes) {
128 printf("uip-ds6-route.c: assert_nbr_routes_list_sane too few entries on route list: should be %d, is %d, max %d\n",
129 num_routes, count, UIP_MAX_ROUTES);
130 }
131#endif /* (UIP_MAX_ROUTES != 0) */
132}
133/*---------------------------------------------------------------------------*/
134#if UIP_DS6_NOTIFICATIONS
135static void
136call_route_callback(int event, const uip_ipaddr_t *route,
137 const uip_ipaddr_t *nexthop)
138{
139 int num;
140 struct uip_ds6_notification *n;
141 for(n = list_head(notificationlist);
142 n != NULL;
143 n = list_item_next(n)) {
144 if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD ||
145 event == UIP_DS6_NOTIFICATION_DEFRT_RM) {
146 num = list_length(defaultrouterlist);
147 } else {
148 num = num_routes;
149 }
150 n->callback(event, route, nexthop, num);
151 }
152}
153/*---------------------------------------------------------------------------*/
154void
155uip_ds6_notification_add(struct uip_ds6_notification *n,
156 uip_ds6_notification_callback c)
157{
158 if(n != NULL && c != NULL) {
159 n->callback = c;
160 list_add(notificationlist, n);
161 }
162}
163/*---------------------------------------------------------------------------*/
164void
165uip_ds6_notification_rm(struct uip_ds6_notification *n)
166{
167 list_remove(notificationlist, n);
168}
169#endif
170/*---------------------------------------------------------------------------*/
171void
172uip_ds6_route_init(void)
173{
174#if (UIP_MAX_ROUTES != 0)
175 memb_init(&routememb);
176 list_init(routelist);
177 nbr_table_register(nbr_routes,
178 (nbr_table_callback *)rm_routelist_callback);
179#endif /* (UIP_MAX_ROUTES != 0) */
180
181 memb_init(&defaultroutermemb);
182 list_init(defaultrouterlist);
183
184#if UIP_DS6_NOTIFICATIONS
185 list_init(notificationlist);
186#endif
187}
188/*---------------------------------------------------------------------------*/
189int
190uip_ds6_route_count_nexthop_neighbors(void)
191{
192#if (UIP_MAX_ROUTES != 0)
193 struct uip_ds6_route_neighbor_routes *entry;
194 int count = 0;
195 for(entry = nbr_table_head(nbr_routes); entry != NULL; entry = nbr_table_next(nbr_routes, entry)) {
196 count++;
197 }
198 return count;
199#else /* (UIP_MAX_ROUTES != 0) */
200 return 0;
201#endif /* (UIP_MAX_ROUTES != 0) */
202}
203#if (UIP_MAX_ROUTES != 0)
204/*---------------------------------------------------------------------------*/
205static uip_lladdr_t *
206uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route)
207{
208 if(route != NULL) {
209 return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes,
210 route->neighbor_routes);
211 } else {
212 return NULL;
213 }
214}
215#endif /* (UIP_MAX_ROUTES != 0) */
216/*---------------------------------------------------------------------------*/
217const uip_ipaddr_t *
218uip_ds6_route_nexthop(uip_ds6_route_t *route)
219{
220#if (UIP_MAX_ROUTES != 0)
221 if(route != NULL) {
222 return uip_ds6_nbr_ipaddr_from_lladdr(uip_ds6_route_nexthop_lladdr(route));
223 } else {
224 return NULL;
225 }
226#else /* (UIP_MAX_ROUTES != 0) */
227 return NULL;
228#endif /* (UIP_MAX_ROUTES != 0) */
229}
230/*---------------------------------------------------------------------------*/
232uip_ds6_route_head(void)
233{
234#if (UIP_MAX_ROUTES != 0)
235 return list_head(routelist);
236#else /* (UIP_MAX_ROUTES != 0) */
237 return NULL;
238#endif /* (UIP_MAX_ROUTES != 0) */
239}
240/*---------------------------------------------------------------------------*/
242uip_ds6_route_next(uip_ds6_route_t *r)
243{
244#if (UIP_MAX_ROUTES != 0)
245 if(r != NULL) {
247 return n;
248 }
249#endif /* (UIP_MAX_ROUTES != 0) */
250 return NULL;
251}
252/*---------------------------------------------------------------------------*/
253int
254uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr)
255{
256#if (UIP_MAX_ROUTES != 0)
257 const uip_lladdr_t *lladdr;
259
260 if(lladdr == NULL) {
261 return 0;
262 }
263
264 return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL;
265#else /* (UIP_MAX_ROUTES != 0) */
266 return 0;
267#endif /* (UIP_MAX_ROUTES != 0) */
268}
269/*---------------------------------------------------------------------------*/
270int
271uip_ds6_route_num_routes(void)
272{
273#if (UIP_MAX_ROUTES != 0)
274 return num_routes;
275#else /* (UIP_MAX_ROUTES != 0) */
276 return 0;
277#endif /* (UIP_MAX_ROUTES != 0) */
278}
279/*---------------------------------------------------------------------------*/
281uip_ds6_route_lookup(const uip_ipaddr_t *addr)
282{
283#if (UIP_MAX_ROUTES != 0)
285 uip_ds6_route_t *found_route;
286 uint8_t longestmatch;
287
288 LOG_INFO("Looking up route for ");
289 LOG_INFO_6ADDR(addr);
290 LOG_INFO_("\n");
291
292 if(addr == NULL) {
293 return NULL;
294 }
295
296 found_route = NULL;
297 longestmatch = 0;
298 for(r = uip_ds6_route_head();
299 r != NULL;
300 r = uip_ds6_route_next(r)) {
301 if(r->length >= longestmatch &&
302 uip_ipaddr_prefixcmp(addr, &r->ipaddr, r->length)) {
303 longestmatch = r->length;
304 found_route = r;
305 /* check if total match - e.g. all 128 bits do match */
306 if(longestmatch == 128) {
307 break;
308 }
309 }
310 }
311
312 if(found_route != NULL) {
313 LOG_INFO("Found route: ");
314 LOG_INFO_6ADDR(addr);
315 LOG_INFO_(" via ");
316 LOG_INFO_6ADDR(uip_ds6_route_nexthop(found_route));
317 LOG_INFO_("\n");
318 } else {
319 LOG_WARN("No route found\n");
320 }
321
322 if(found_route != NULL && found_route != list_head(routelist)) {
323 /* If we found a route, we put it at the start of the routeslist
324 list. The list is ordered by how recently we looked them up:
325 the least recently used route will be at the end of the
326 list - for fast lookups (assuming multiple packets to the same node). */
327
328 list_remove(routelist, found_route);
329 list_push(routelist, found_route);
330 }
331
332 return found_route;
333#else /* (UIP_MAX_ROUTES != 0) */
334 return NULL;
335#endif /* (UIP_MAX_ROUTES != 0) */
336}
337/*---------------------------------------------------------------------------*/
339uip_ds6_route_add(const uip_ipaddr_t *ipaddr, uint8_t length,
340 const uip_ipaddr_t *nexthop)
341{
342#if (UIP_MAX_ROUTES != 0)
344 struct uip_ds6_route_neighbor_route *nbrr;
345
346 if(LOG_DBG_ENABLED) {
347 assert_nbr_routes_list_sane();
348 }
349
350 if(ipaddr == NULL || nexthop == NULL) {
351 return NULL;
352 }
353
354 /* Get link-layer address of next hop, make sure it is in neighbor table */
355 const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
356 if(nexthop_lladdr == NULL) {
357 LOG_WARN("Add: neighbor link-local address unknown for ");
358 LOG_WARN_6ADDR(nexthop);
359 LOG_WARN_("\n");
360 return NULL;
361 }
362
363 /* First make sure that we don't add a route twice. If we find an
364 existing route for our destination, we'll delete the old
365 one first. */
366 r = uip_ds6_route_lookup(ipaddr);
367 if(r != NULL) {
368 const uip_ipaddr_t *current_nexthop;
369 current_nexthop = uip_ds6_route_nexthop(r);
370 if(current_nexthop != NULL && uip_ipaddr_cmp(nexthop, current_nexthop)) {
371 /* no need to update route - already correct! */
372 return r;
373 }
374 LOG_INFO("Add: old route for ");
375 LOG_INFO_6ADDR(ipaddr);
376 LOG_INFO_(" found, deleting it\n");
377
378 uip_ds6_route_rm(r);
379 }
380 {
381 struct uip_ds6_route_neighbor_routes *routes;
382 /* If there is no routing entry, create one. We first need to
383 check if we have room for this route. If not, we remove the
384 least recently used one we have. */
385
386 if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) {
387 uip_ds6_route_t *oldest;
388 oldest = NULL;
389#if UIP_DS6_ROUTE_REMOVE_LEAST_RECENTLY_USED
390 /* Removing the oldest route entry from the route table. The
391 least recently used route is the first route on the list. */
392 oldest = list_tail(routelist);
393#endif
394 if(oldest == NULL) {
395 return NULL;
396 }
397 LOG_INFO("Add: dropping route to ");
398 LOG_INFO_6ADDR(&oldest->ipaddr);
399 LOG_INFO_("\n");
400 uip_ds6_route_rm(oldest);
401 }
402
403
404 /* Every neighbor on our neighbor table holds a struct
405 uip_ds6_route_neighbor_routes which holds a list of routes that
406 go through the neighbor. We add our route entry to this list.
407
408 We first check to see if we already have this neighbor in our
409 nbr_route table. If so, the neighbor already has a route entry
410 list.
411 */
412 routes = nbr_table_get_from_lladdr(nbr_routes,
413 (linkaddr_t *)nexthop_lladdr);
414
415 if(routes == NULL) {
416 /* If the neighbor did not have an entry in our neighbor table,
417 we create one. The nbr_table_add_lladdr() function returns a
418 pointer to a pointer that we may use for our own purposes. We
419 initialize this pointer with the list of routing entries that
420 are attached to this neighbor. */
421 routes = nbr_table_add_lladdr(nbr_routes,
422 (linkaddr_t *)nexthop_lladdr,
423 NBR_TABLE_REASON_ROUTE, NULL);
424 if(routes == NULL) {
425 /* This should not happen, as we explicitly deallocated one
426 route table entry above. */
427 LOG_ERR("Add: could not allocate neighbor table entry\n");
428 return NULL;
429 }
430 LIST_STRUCT_INIT(routes, route_list);
431#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
432 NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK((const linkaddr_t *)nexthop_lladdr);
433#endif
434 }
435
436 /* Allocate a routing entry and populate it. */
437 r = memb_alloc(&routememb);
438
439 if(r == NULL) {
440 /* This should not happen, as we explicitly deallocated one
441 route table entry above. */
442 LOG_ERR("Add: could not allocate route\n");
443 return NULL;
444 }
445
446 /* add new routes first - assuming that there is a reason to add this
447 and that there is a packet coming soon. */
448 list_push(routelist, r);
449
450 nbrr = memb_alloc(&neighborroutememb);
451 if(nbrr == NULL) {
452 /* This should not happen, as we explicitly deallocated one
453 route table entry above. */
454 LOG_ERR("Add: could not allocate neighbor route list entry\n");
455 memb_free(&routememb, r);
456 return NULL;
457 }
458
459 nbrr->route = r;
460 /* Add the route to this neighbor */
461 list_add(routes->route_list, nbrr);
462 r->neighbor_routes = routes;
463 num_routes++;
464
465 LOG_INFO("Add: num %d\n", num_routes);
466
467 /* lock this entry so that nexthop is not removed */
468 nbr_table_lock(nbr_routes, routes);
469 }
470
471 uip_ipaddr_copy(&(r->ipaddr), ipaddr);
472 r->length = length;
473
474#ifdef UIP_DS6_ROUTE_STATE_TYPE
475 memset(&r->state, 0, sizeof(UIP_DS6_ROUTE_STATE_TYPE));
476#endif
477
478 LOG_INFO("Add: adding route: ");
479 LOG_INFO_6ADDR(ipaddr);
480 LOG_INFO_(" via ");
481 LOG_INFO_6ADDR(nexthop);
482 LOG_INFO_("\n");
483 LOG_ANNOTATE("#L %u 1;blue\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
484
485#if UIP_DS6_NOTIFICATIONS
486 call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop);
487#endif
488
489 if(LOG_DBG_ENABLED) {
490 assert_nbr_routes_list_sane();
491 }
492 return r;
493
494#else /* (UIP_MAX_ROUTES != 0) */
495 return NULL;
496#endif /* (UIP_MAX_ROUTES != 0) */
497}
498
499/*---------------------------------------------------------------------------*/
500void
501uip_ds6_route_rm(uip_ds6_route_t *route)
502{
503#if (UIP_MAX_ROUTES != 0)
504 struct uip_ds6_route_neighbor_route *neighbor_route;
505
506 if(LOG_DBG_ENABLED) {
507 assert_nbr_routes_list_sane();
508 }
509
510 if(route != NULL && route->neighbor_routes != NULL) {
511
512 LOG_INFO("Rm: removing route: ");
513 LOG_INFO_6ADDR(&route->ipaddr);
514 LOG_INFO_("\n");
515
516 /* Remove the route from the route list */
517 list_remove(routelist, route);
518
519 /* Find the corresponding neighbor_route and remove it. */
520 for(neighbor_route = list_head(route->neighbor_routes->route_list);
521 neighbor_route != NULL && neighbor_route->route != route;
522 neighbor_route = list_item_next(neighbor_route));
523
524 if(neighbor_route == NULL) {
525 LOG_INFO("Rm: neighbor_route was NULL for ");
526 LOG_INFO_6ADDR(&route->ipaddr);
527 LOG_INFO_("\n");
528 }
529 list_remove(route->neighbor_routes->route_list, neighbor_route);
530 if(list_head(route->neighbor_routes->route_list) == NULL) {
531 /* If this was the only route using this neighbor, remove the
532 neighbor from the table - this implicitly unlocks nexthop */
533#if LOG_WITH_ANNOTATE
534 const uip_ipaddr_t *nexthop = uip_ds6_route_nexthop(route);
535 if(nexthop != NULL) {
536 LOG_ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
537 }
538#endif /* LOG_WITH_ANNOTATE */
539 LOG_INFO("Rm: removing neighbor too\n");
540 nbr_table_remove(nbr_routes, route->neighbor_routes->route_list);
541#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
542 NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(
543 (const linkaddr_t *)nbr_table_get_lladdr(nbr_routes, route->neighbor_routes->route_list));
544#endif
545 }
546 memb_free(&routememb, route);
547 memb_free(&neighborroutememb, neighbor_route);
548
549 num_routes--;
550
551 LOG_INFO("Rm: num %d\n", num_routes);
552
553#if UIP_DS6_NOTIFICATIONS
554 call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
555 &route->ipaddr, uip_ds6_route_nexthop(route));
556#endif
557 }
558
559 if(LOG_DBG_ENABLED) {
560 assert_nbr_routes_list_sane();
561 }
562
563#endif /* (UIP_MAX_ROUTES != 0) */
564 return;
565}
566#if (UIP_MAX_ROUTES != 0)
567/*---------------------------------------------------------------------------*/
568static void
569rm_routelist(struct uip_ds6_route_neighbor_routes *routes)
570{
571 if(LOG_DBG_ENABLED) {
572 assert_nbr_routes_list_sane();
573 }
574
575 if(routes != NULL && routes->route_list != NULL) {
577 r = list_head(routes->route_list);
578 while(r != NULL) {
579 uip_ds6_route_rm(r->route);
580 r = list_head(routes->route_list);
581 }
582 nbr_table_remove(nbr_routes, routes);
583 }
584
585 if(LOG_DBG_ENABLED) {
586 assert_nbr_routes_list_sane();
587 }
588}
589/*---------------------------------------------------------------------------*/
590static void
591rm_routelist_callback(nbr_table_item_t *ptr)
592{
593 rm_routelist((struct uip_ds6_route_neighbor_routes *)ptr);
594}
595#endif /* (UIP_MAX_ROUTES != 0) */
596/*---------------------------------------------------------------------------*/
597void
598uip_ds6_route_rm_by_nexthop(const uip_ipaddr_t *nexthop)
599{
600#if (UIP_MAX_ROUTES != 0)
601 /* Get routing entry list of this neighbor */
602 const uip_lladdr_t *nexthop_lladdr;
603 struct uip_ds6_route_neighbor_routes *routes;
604
605 nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
606 routes = nbr_table_get_from_lladdr(nbr_routes,
607 (linkaddr_t *)nexthop_lladdr);
608 rm_routelist(routes);
609#endif /* (UIP_MAX_ROUTES != 0) */
610}
611/*---------------------------------------------------------------------------*/
613uip_ds6_defrt_head(void)
614{
615 return list_head(defaultrouterlist);
616}
617/*---------------------------------------------------------------------------*/
619uip_ds6_defrt_add(const uip_ipaddr_t *ipaddr, unsigned long interval)
620{
622
623 if(LOG_DBG_ENABLED) {
624 assert_nbr_routes_list_sane();
625 }
626
627 if(ipaddr == NULL) {
628 return NULL;
629 }
630
631 d = uip_ds6_defrt_lookup(ipaddr);
632 if(d == NULL) {
633 d = memb_alloc(&defaultroutermemb);
634 if(d == NULL) {
635 LOG_ERR("Add default: could not add default route to ");
636 LOG_ERR_6ADDR(ipaddr);
637 LOG_ERR_(", out of memory\n");
638 return NULL;
639 } else {
640 LOG_INFO("Add default: adding default route to ");
641 LOG_INFO_6ADDR(ipaddr);
642 LOG_INFO_("\n");
643 }
644
645 list_push(defaultrouterlist, d);
646 }
647 else {
648 LOG_INFO("Refreshing default\n");
649 }
650
651 uip_ipaddr_copy(&d->ipaddr, ipaddr);
652 if(interval != 0) {
653 stimer_set(&d->lifetime, interval);
654 d->isinfinite = 0;
655 } else {
656 d->isinfinite = 1;
657 }
658
659 LOG_ANNOTATE("#L %u 1\n", ipaddr->u8[sizeof(uip_ipaddr_t) - 1]);
660
661#if UIP_DS6_NOTIFICATIONS
662 call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr);
663#endif
664
665if(LOG_DBG_ENABLED) {
666 assert_nbr_routes_list_sane();
667}
668
669 return d;
670}
671/*---------------------------------------------------------------------------*/
672void
673uip_ds6_defrt_rm(uip_ds6_defrt_t *defrt)
674{
676
677 if(LOG_DBG_ENABLED) {
678 assert_nbr_routes_list_sane();
679 }
680
681 /* Make sure that the defrt is in the list before we remove it. */
682 for(d = list_head(defaultrouterlist);
683 d != NULL;
684 d = list_item_next(d)) {
685 if(d == defrt) {
686 LOG_INFO("Removing default\n");
687 list_remove(defaultrouterlist, defrt);
688 memb_free(&defaultroutermemb, defrt);
689 LOG_ANNOTATE("#L %u 0\n", defrt->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]);
690#if UIP_DS6_NOTIFICATIONS
691 call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_RM,
692 &defrt->ipaddr, &defrt->ipaddr);
693#endif
694 return;
695 }
696 }
697
698 if(LOG_DBG_ENABLED) {
699 assert_nbr_routes_list_sane();
700 }
701}
702/*---------------------------------------------------------------------------*/
704uip_ds6_defrt_lookup(const uip_ipaddr_t *ipaddr)
705{
707 if(ipaddr == NULL) {
708 return NULL;
709 }
710 for(d = list_head(defaultrouterlist);
711 d != NULL;
712 d = list_item_next(d)) {
713 if(uip_ipaddr_cmp(&d->ipaddr, ipaddr)) {
714 return d;
715 }
716 }
717 return NULL;
718}
719/*---------------------------------------------------------------------------*/
720const uip_ipaddr_t *
721uip_ds6_defrt_choose(void)
722{
724 uip_ds6_nbr_t *bestnbr;
725 uip_ipaddr_t *addr;
726
727 addr = NULL;
728 for(d = list_head(defaultrouterlist);
729 d != NULL;
730 d = list_item_next(d)) {
731 LOG_INFO("Default route, IP address ");
732 LOG_INFO_6ADDR(&d->ipaddr);
733 LOG_INFO_("\n");
734 bestnbr = uip_ds6_nbr_lookup(&d->ipaddr);
735 if(bestnbr != NULL && bestnbr->state != NBR_INCOMPLETE) {
736 LOG_INFO("Default route found, IP address ");
737 LOG_INFO_6ADDR(&d->ipaddr);
738 LOG_INFO_("\n");
739 return &d->ipaddr;
740 } else {
741 addr = &d->ipaddr;
742 LOG_INFO("Default route Incomplete found, IP address ");
743 LOG_INFO_6ADDR(&d->ipaddr);
744 LOG_INFO_("\n");
745 }
746 }
747 return addr;
748}
749/*---------------------------------------------------------------------------*/
750void
751uip_ds6_defrt_periodic(void)
752{
754 d = list_head(defaultrouterlist);
755 while(d != NULL) {
756 if(!d->isinfinite &&
757 stimer_expired(&d->lifetime)) {
758 LOG_INFO("Default route periodic: defrt lifetime expired\n");
759 uip_ds6_defrt_rm(d);
760 d = list_head(defaultrouterlist);
761 } else {
762 d = list_item_next(d);
763 }
764 }
765}
766/*---------------------------------------------------------------------------*/
767/** @} */
static volatile uint64_t count
Num.
Definition: clock.c:50
void list_init(list_t list)
Initialize a list.
Definition: list.c:65
void * list_head(const list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
#define LIST(name)
Declare a linked list.
Definition: list.h:89
int list_length(const list_t list)
Get the length of a list.
Definition: list.c:272
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:142
void list_remove(list_t list, const void *item)
Remove a specific element from a list.
Definition: list.c:237
void * list_tail(const list_t list)
Get the tail of a list.
Definition: list.c:117
void * list_item_next(const void *item)
Get the next item following this item.
Definition: list.c:322
void list_push(list_t list, void *item)
Add an item to the start of the list.
Definition: list.c:164
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
Definition: list.h:125
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:78
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition: memb.c:52
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:90
int stimer_expired(struct stimer *t)
Check if a timer has expired.
Definition: stimer.c:127
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
Definition: stimer.c:67
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
Definition: uip-ds6-nbr.h:64
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
Definition: uip-ds6-nbr.c:467
#define UIP_DS6_ROUTE_STATE_TYPE
define some additional RPL related route state and neighbor callback for RPL - if not a DS6_ROUTE_STA...
const uip_lladdr_t * uip_ds6_nbr_lladdr_from_ipaddr(const uip_ipaddr_t *ipaddr)
Get the link-layer address associated with a specified IPv6 address.
Definition: uip-ds6-nbr.c:513
uip_ipaddr_t * uip_ds6_nbr_ipaddr_from_lladdr(const uip_lladdr_t *lladdr)
Get an IPv6 address associated with a specified link-layer address.
Definition: uip-ds6-nbr.c:505
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:969
Linked list manipulation routines.
Header file for the logging system.
Memory block allocation routines.
An entry in the default router list.
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
Definition: uip-ds6-nbr.h:105
A neighbor route list entry, used on the uip_ds6_route->neighbor_routes->route_list list.
The neighbor routes hold a list of routing table entries that are attached to a specific neihbor.
An entry in the routing table.
Header file for routing table manipulation.
Header file for IPv6-related data structures.
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:116
static uip_ds6_defrt_t * defrt
Pointer to an interface address.
Definition: uip-nd6.c:111
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
Header file for the uIP TCP/IP stack.