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