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.
static void list_init(list_t list)
Initialize a list.
#define LIST(name)
Declare a linked list.
static void * list_item_next(const void *item)
Get the next item following this item.
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_push(list_t list, void *item)
Add an item to the start of the 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.
static void * list_head(const_list_t list)
Get a pointer to the first element of a list.
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.
static void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
bool stimer_expired(struct stimer *t)
Check if a timer has expired.
struct uip_ds6_route uip_ds6_route_t
An entry in the routing table.
#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.
struct uip_ds6_defrt uip_ds6_defrt_t
An entry in the default router list.
#define UIP_DS6_ROUTE_STATE_TYPE
define some additional RPL related route state and neighbor callback for RPL - if not a DS6_ROUTE_STA...
struct uip_ds6_nbr uip_ds6_nbr_t
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...
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.
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.
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.