47#include "net/nbr-table.h"
51#define LOG_MODULE "IPv6 Route"
52#define LOG_LEVEL LOG_LEVEL_IPV6
54#if BUILD_WITH_ORCHESTRA
57#ifndef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
58#define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added
60void NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK(
const linkaddr_t *
addr);
63#ifndef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK
64#define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed
66void NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(
const linkaddr_t *
addr);
70#if (UIP_MAX_ROUTES != 0)
85static int num_routes = 0;
86static void rm_routelist_callback(nbr_table_item_t *ptr);
92LIST(defaultrouterlist);
95#if UIP_DS6_NOTIFICATIONS
96LIST(notificationlist);
101assert_nbr_routes_list_sane(
void)
107 for(r = uip_ds6_route_head(),
110 count < UIP_DS6_ROUTE_NB * 2;
111 r = uip_ds6_route_next(r),
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");
118#if (UIP_MAX_ROUTES != 0)
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);
128#if UIP_DS6_NOTIFICATIONS
130call_route_callback(
int event,
const uip_ipaddr_t *route,
131 const uip_ipaddr_t *nexthop)
134 struct uip_ds6_notification *n;
138 if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD ||
139 event == UIP_DS6_NOTIFICATION_DEFRT_RM) {
144 n->callback(event, route, nexthop, num);
149uip_ds6_notification_add(
struct uip_ds6_notification *n,
150 uip_ds6_notification_callback c)
152 if(n != NULL && c != NULL) {
159uip_ds6_notification_rm(
struct uip_ds6_notification *n)
166uip_ds6_route_init(
void)
168#if (UIP_MAX_ROUTES != 0)
171 nbr_table_register(nbr_routes,
172 (nbr_table_callback *)rm_routelist_callback);
178#if UIP_DS6_NOTIFICATIONS
184uip_ds6_route_count_nexthop_neighbors(
void)
186#if (UIP_MAX_ROUTES != 0)
189 for(entry = nbr_table_head(nbr_routes); entry != NULL; entry = nbr_table_next(nbr_routes, entry)) {
197#if (UIP_MAX_ROUTES != 0)
203 return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes,
204 route->neighbor_routes);
214#if (UIP_MAX_ROUTES != 0)
226uip_ds6_route_head(
void)
228#if (UIP_MAX_ROUTES != 0)
238#if (UIP_MAX_ROUTES != 0)
248uip_ds6_route_is_nexthop(
const uip_ipaddr_t *
ipaddr)
250#if (UIP_MAX_ROUTES != 0)
251 const uip_lladdr_t *lladdr;
258 return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL;
265uip_ds6_route_num_routes(
void)
267#if (UIP_MAX_ROUTES != 0)
275uip_ds6_route_lookup(
const uip_ipaddr_t *
addr)
277#if (UIP_MAX_ROUTES != 0)
280 uint8_t longestmatch;
282 LOG_INFO(
"Looking up route for ");
283 LOG_INFO_6ADDR(
addr);
292 for(r = uip_ds6_route_head();
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;
300 if(longestmatch == 128) {
306 if(found_route != NULL) {
307 LOG_INFO(
"Found route: ");
308 LOG_INFO_6ADDR(
addr);
310 LOG_INFO_6ADDR(uip_ds6_route_nexthop(found_route));
313 LOG_INFO(
"No route found\n");
316 if(found_route != NULL && found_route !=
list_head(routelist)) {
333uip_ds6_route_add(
const uip_ipaddr_t *
ipaddr, uint8_t length,
334 const uip_ipaddr_t *nexthop)
336#if (UIP_MAX_ROUTES != 0)
340 if(LOG_DBG_ENABLED) {
341 assert_nbr_routes_list_sane();
344 if(
ipaddr == NULL || nexthop == NULL) {
350 if(nexthop_lladdr == NULL) {
351 LOG_WARN(
"Add: neighbor link-local address unknown for ");
352 LOG_WARN_6ADDR(nexthop);
360 r = uip_ds6_route_lookup(
ipaddr);
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)) {
368 LOG_INFO(
"Add: old route for ");
370 LOG_INFO_(
" found, deleting it\n");
380 if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) {
383#if UIP_DS6_ROUTE_REMOVE_LEAST_RECENTLY_USED
391 LOG_INFO(
"Add: dropping route to ");
392 LOG_INFO_6ADDR(&oldest->ipaddr);
394 uip_ds6_route_rm(oldest);
406 routes = nbr_table_get_from_lladdr(nbr_routes,
407 (linkaddr_t *)nexthop_lladdr);
415 routes = nbr_table_add_lladdr(nbr_routes,
416 (linkaddr_t *)nexthop_lladdr,
417 NBR_TABLE_REASON_ROUTE, NULL);
421 LOG_ERR(
"Add: could not allocate neighbor table entry\n");
425#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK
426 NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK((
const linkaddr_t *)nexthop_lladdr);
436 LOG_ERR(
"Add: could not allocate route\n");
448 LOG_ERR(
"Add: could not allocate neighbor route list entry\n");
456 r->neighbor_routes = routes;
459 LOG_INFO(
"Add: num %d\n", num_routes);
462 nbr_table_lock(nbr_routes, routes);
468#ifdef UIP_DS6_ROUTE_STATE_TYPE
472 LOG_INFO(
"Add: adding route: ");
475 LOG_INFO_6ADDR(nexthop);
477 LOG_ANNOTATE(
"#L %u 1;blue\n", nexthop->u8[
sizeof(uip_ipaddr_t) - 1]);
479#if UIP_DS6_NOTIFICATIONS
480 call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD,
ipaddr, nexthop);
483 if(LOG_DBG_ENABLED) {
484 assert_nbr_routes_list_sane();
497#if (UIP_MAX_ROUTES != 0)
500 if(LOG_DBG_ENABLED) {
501 assert_nbr_routes_list_sane();
504 if(route != NULL && route->neighbor_routes != NULL) {
506 LOG_INFO(
"Rm: removing route: ");
507 LOG_INFO_6ADDR(&route->ipaddr);
514 for(neighbor_route =
list_head(route->neighbor_routes->route_list);
515 neighbor_route != NULL && neighbor_route->route != route;
518 if(neighbor_route == NULL) {
519 LOG_INFO(
"Rm: neighbor_route was NULL for ");
520 LOG_INFO_6ADDR(&route->ipaddr);
523 list_remove(route->neighbor_routes->route_list, neighbor_route);
524 if(
list_head(route->neighbor_routes->route_list) == NULL) {
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]);
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));
541 memb_free(&neighborroutememb, neighbor_route);
545 LOG_INFO(
"Rm: num %d\n", num_routes);
547#if UIP_DS6_NOTIFICATIONS
548 call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
549 &route->ipaddr, uip_ds6_route_nexthop(route));
553 if(LOG_DBG_ENABLED) {
554 assert_nbr_routes_list_sane();
560#if (UIP_MAX_ROUTES != 0)
565 if(LOG_DBG_ENABLED) {
566 assert_nbr_routes_list_sane();
569 if(routes != NULL && routes->route_list != NULL) {
573 uip_ds6_route_rm(r->route);
576 nbr_table_remove(nbr_routes, routes);
579 if(LOG_DBG_ENABLED) {
580 assert_nbr_routes_list_sane();
585rm_routelist_callback(nbr_table_item_t *ptr)
592uip_ds6_route_rm_by_nexthop(
const uip_ipaddr_t *nexthop)
594#if (UIP_MAX_ROUTES != 0)
596 const uip_lladdr_t *nexthop_lladdr;
600 routes = nbr_table_get_from_lladdr(nbr_routes,
601 (linkaddr_t *)nexthop_lladdr);
602 rm_routelist(routes);
607uip_ds6_defrt_head(
void)
613uip_ds6_defrt_add(
const uip_ipaddr_t *
ipaddr,
unsigned long interval)
617 if(LOG_DBG_ENABLED) {
618 assert_nbr_routes_list_sane();
625 d = uip_ds6_defrt_lookup(
ipaddr);
629 LOG_ERR(
"Add default: could not add default route to ");
631 LOG_ERR_(
", out of memory\n");
634 LOG_INFO(
"Add default: adding default route to ");
642 LOG_INFO(
"Refreshing default\n");
653 LOG_ANNOTATE(
"#L %u 1\n",
ipaddr->u8[
sizeof(uip_ipaddr_t) - 1]);
655#if UIP_DS6_NOTIFICATIONS
656 call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD,
ipaddr,
ipaddr);
660 assert_nbr_routes_list_sane();
671 if(LOG_DBG_ENABLED) {
672 assert_nbr_routes_list_sane();
680 LOG_INFO(
"Removing default\n");
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,
692 if(LOG_DBG_ENABLED) {
693 assert_nbr_routes_list_sane();
698uip_ds6_defrt_lookup(
const uip_ipaddr_t *
ipaddr)
707 if(uip_ipaddr_cmp(&d->ipaddr,
ipaddr)) {
715uip_ds6_defrt_choose(
void)
725 LOG_INFO(
"Default route, IP address ");
726 LOG_INFO_6ADDR(&d->ipaddr);
730 LOG_INFO(
"Default route found, IP address ");
731 LOG_INFO_6ADDR(&d->ipaddr);
736 LOG_INFO(
"Default route Incomplete found, IP address ");
737 LOG_INFO_6ADDR(&d->ipaddr);
745uip_ds6_defrt_periodic(
void)
752 LOG_INFO(
"Default route periodic: defrt lifetime expired\n");
static volatile uint64_t count
Num.
void list_init(list_t list)
Initialize 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_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.
void * list_head(const_list_t list)
Get a pointer to the first element of a list.
void * list_tail(const_list_t list)
Get the tail of a 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.