47#include "net/nbr-table.h"
51#define LOG_MODULE "IPv6 Route"
52#define LOG_LEVEL LOG_LEVEL_IPV6
54#if BUILD_WITH_ORCHESTRA
56#ifndef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
57#define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added
60#ifndef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
61#define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed
67#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
68void NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK(
const linkaddr_t *
addr);
72#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
73void NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(
const linkaddr_t *
addr);
76#if (UIP_MAX_ROUTES != 0)
91static int num_routes = 0;
92static void rm_routelist_callback(nbr_table_item_t *ptr);
98LIST(defaultrouterlist);
101#if UIP_DS6_NOTIFICATIONS
102LIST(notificationlist);
107assert_nbr_routes_list_sane(
void)
113 for(r = uip_ds6_route_head(),
116 count < UIP_DS6_ROUTE_NB * 2;
117 r = uip_ds6_route_next(r),
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");
124#if (UIP_MAX_ROUTES != 0)
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);
134#if UIP_DS6_NOTIFICATIONS
136call_route_callback(
int event,
const uip_ipaddr_t *route,
137 const uip_ipaddr_t *nexthop)
140 struct uip_ds6_notification *n;
144 if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD ||
145 event == UIP_DS6_NOTIFICATION_DEFRT_RM) {
150 n->callback(event, route, nexthop, num);
155uip_ds6_notification_add(
struct uip_ds6_notification *n,
156 uip_ds6_notification_callback c)
158 if(n != NULL && c != NULL) {
165uip_ds6_notification_rm(
struct uip_ds6_notification *n)
172uip_ds6_route_init(
void)
174#if (UIP_MAX_ROUTES != 0)
177 nbr_table_register(nbr_routes,
178 (nbr_table_callback *)rm_routelist_callback);
184#if UIP_DS6_NOTIFICATIONS
190uip_ds6_route_count_nexthop_neighbors(
void)
192#if (UIP_MAX_ROUTES != 0)
195 for(entry = nbr_table_head(nbr_routes); entry != NULL; entry = nbr_table_next(nbr_routes, entry)) {
203#if (UIP_MAX_ROUTES != 0)
209 return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes,
210 route->neighbor_routes);
220#if (UIP_MAX_ROUTES != 0)
232uip_ds6_route_head(
void)
234#if (UIP_MAX_ROUTES != 0)
244#if (UIP_MAX_ROUTES != 0)
254uip_ds6_route_is_nexthop(
const uip_ipaddr_t *
ipaddr)
256#if (UIP_MAX_ROUTES != 0)
257 const uip_lladdr_t *lladdr;
264 return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL;
271uip_ds6_route_num_routes(
void)
273#if (UIP_MAX_ROUTES != 0)
281uip_ds6_route_lookup(
const uip_ipaddr_t *
addr)
283#if (UIP_MAX_ROUTES != 0)
286 uint8_t longestmatch;
288 LOG_INFO(
"Looking up route for ");
289 LOG_INFO_6ADDR(
addr);
298 for(r = uip_ds6_route_head();
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;
306 if(longestmatch == 128) {
312 if(found_route != NULL) {
313 LOG_INFO(
"Found route: ");
314 LOG_INFO_6ADDR(
addr);
316 LOG_INFO_6ADDR(uip_ds6_route_nexthop(found_route));
319 LOG_WARN(
"No route found\n");
322 if(found_route != NULL && found_route !=
list_head(routelist)) {
339uip_ds6_route_add(
const uip_ipaddr_t *
ipaddr, uint8_t length,
340 const uip_ipaddr_t *nexthop)
342#if (UIP_MAX_ROUTES != 0)
346 if(LOG_DBG_ENABLED) {
347 assert_nbr_routes_list_sane();
350 if(
ipaddr == NULL || nexthop == NULL) {
356 if(nexthop_lladdr == NULL) {
357 LOG_WARN(
"Add: neighbor link-local address unknown for ");
358 LOG_WARN_6ADDR(nexthop);
366 r = uip_ds6_route_lookup(
ipaddr);
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)) {
374 LOG_INFO(
"Add: old route for ");
376 LOG_INFO_(
" found, deleting it\n");
386 if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) {
389#if UIP_DS6_ROUTE_REMOVE_LEAST_RECENTLY_USED
397 LOG_INFO(
"Add: dropping route to ");
398 LOG_INFO_6ADDR(&oldest->ipaddr);
400 uip_ds6_route_rm(oldest);
412 routes = nbr_table_get_from_lladdr(nbr_routes,
413 (linkaddr_t *)nexthop_lladdr);
421 routes = nbr_table_add_lladdr(nbr_routes,
422 (linkaddr_t *)nexthop_lladdr,
423 NBR_TABLE_REASON_ROUTE, NULL);
427 LOG_ERR(
"Add: could not allocate neighbor table entry\n");
431#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
432 NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK((
const linkaddr_t *)nexthop_lladdr);
442 LOG_ERR(
"Add: could not allocate route\n");
454 LOG_ERR(
"Add: could not allocate neighbor route list entry\n");
462 r->neighbor_routes = routes;
465 LOG_INFO(
"Add: num %d\n", num_routes);
468 nbr_table_lock(nbr_routes, routes);
474#ifdef UIP_DS6_ROUTE_STATE_TYPE
478 LOG_INFO(
"Add: adding route: ");
481 LOG_INFO_6ADDR(nexthop);
483 LOG_ANNOTATE(
"#L %u 1;blue\n", nexthop->u8[
sizeof(uip_ipaddr_t) - 1]);
485#if UIP_DS6_NOTIFICATIONS
486 call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD,
ipaddr, nexthop);
489 if(LOG_DBG_ENABLED) {
490 assert_nbr_routes_list_sane();
503#if (UIP_MAX_ROUTES != 0)
506 if(LOG_DBG_ENABLED) {
507 assert_nbr_routes_list_sane();
510 if(route != NULL && route->neighbor_routes != NULL) {
512 LOG_INFO(
"Rm: removing route: ");
513 LOG_INFO_6ADDR(&route->ipaddr);
520 for(neighbor_route =
list_head(route->neighbor_routes->route_list);
521 neighbor_route != NULL && neighbor_route->route != route;
524 if(neighbor_route == NULL) {
525 LOG_INFO(
"Rm: neighbor_route was NULL for ");
526 LOG_INFO_6ADDR(&route->ipaddr);
529 list_remove(route->neighbor_routes->route_list, neighbor_route);
530 if(
list_head(route->neighbor_routes->route_list) == NULL) {
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]);
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));
547 memb_free(&neighborroutememb, neighbor_route);
551 LOG_INFO(
"Rm: num %d\n", num_routes);
553#if UIP_DS6_NOTIFICATIONS
554 call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
555 &route->ipaddr, uip_ds6_route_nexthop(route));
559 if(LOG_DBG_ENABLED) {
560 assert_nbr_routes_list_sane();
566#if (UIP_MAX_ROUTES != 0)
571 if(LOG_DBG_ENABLED) {
572 assert_nbr_routes_list_sane();
575 if(routes != NULL && routes->route_list != NULL) {
579 uip_ds6_route_rm(r->route);
582 nbr_table_remove(nbr_routes, routes);
585 if(LOG_DBG_ENABLED) {
586 assert_nbr_routes_list_sane();
591rm_routelist_callback(nbr_table_item_t *ptr)
598uip_ds6_route_rm_by_nexthop(
const uip_ipaddr_t *nexthop)
600#if (UIP_MAX_ROUTES != 0)
602 const uip_lladdr_t *nexthop_lladdr;
606 routes = nbr_table_get_from_lladdr(nbr_routes,
607 (linkaddr_t *)nexthop_lladdr);
608 rm_routelist(routes);
613uip_ds6_defrt_head(
void)
619uip_ds6_defrt_add(
const uip_ipaddr_t *
ipaddr,
unsigned long interval)
623 if(LOG_DBG_ENABLED) {
624 assert_nbr_routes_list_sane();
631 d = uip_ds6_defrt_lookup(
ipaddr);
635 LOG_ERR(
"Add default: could not add default route to ");
637 LOG_ERR_(
", out of memory\n");
640 LOG_INFO(
"Add default: adding default route to ");
648 LOG_INFO(
"Refreshing default\n");
659 LOG_ANNOTATE(
"#L %u 1\n",
ipaddr->u8[
sizeof(uip_ipaddr_t) - 1]);
661#if UIP_DS6_NOTIFICATIONS
662 call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD,
ipaddr,
ipaddr);
666 assert_nbr_routes_list_sane();
677 if(LOG_DBG_ENABLED) {
678 assert_nbr_routes_list_sane();
686 LOG_INFO(
"Removing default\n");
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,
698 if(LOG_DBG_ENABLED) {
699 assert_nbr_routes_list_sane();
704uip_ds6_defrt_lookup(
const uip_ipaddr_t *
ipaddr)
713 if(uip_ipaddr_cmp(&d->ipaddr,
ipaddr)) {
721uip_ds6_defrt_choose(
void)
731 LOG_INFO(
"Default route, IP address ");
732 LOG_INFO_6ADDR(&d->ipaddr);
736 LOG_INFO(
"Default route found, IP address ");
737 LOG_INFO_6ADDR(&d->ipaddr);
742 LOG_INFO(
"Default route Incomplete found, IP address ");
743 LOG_INFO_6ADDR(&d->ipaddr);
751uip_ds6_defrt_periodic(
void)
758 LOG_INFO(
"Default route periodic: defrt lifetime expired\n");
static volatile uint64_t count
Num.
void list_init(list_t list)
Initialize a list.
void * list_head(const list_t list)
Get a pointer to the first element of a list.
#define LIST(name)
Declare a linked list.
int list_length(const list_t list)
Get the length of a list.
void list_add(list_t list, void *item)
Add an item at the end of a list.
void list_remove(list_t list, const void *item)
Remove a specific element from a list.
void * list_tail(const list_t list)
Get the tail of a list.
void * list_item_next(const void *item)
Get the next item following this item.
void list_push(list_t list, void *item)
Add an item to the start of the list.
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
#define MEMB(name, structure, num)
Declare a memory block.
int stimer_expired(struct stimer *t)
Check if a timer has expired.
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
uip_ds6_nbr_t * uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
Get the neighbor cache associated with a specified IPv6 address.
#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.
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.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
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...
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.
static uip_ds6_defrt_t * defrt
Pointer to an interface address.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Header file for the uIP TCP/IP stack.