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 68 void NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK(
const linkaddr_t *
addr);
72 #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK 73 void NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(
const linkaddr_t *
addr);
76 #if (UIP_MAX_ROUTES != 0) 91 static int num_routes = 0;
92 static void rm_routelist_callback(nbr_table_item_t *ptr);
98 LIST(defaultrouterlist);
101 #if UIP_DS6_NOTIFICATIONS 102 LIST(notificationlist);
107 assert_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 136 call_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);
155 uip_ds6_notification_add(
struct uip_ds6_notification *n,
156 uip_ds6_notification_callback c)
158 if(n != NULL && c != NULL) {
165 uip_ds6_notification_rm(
struct uip_ds6_notification *n)
172 uip_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 190 uip_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) 205 static uip_lladdr_t *
209 return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes,
210 route->neighbor_routes);
220 #if (UIP_MAX_ROUTES != 0) 232 uip_ds6_route_head(
void)
234 #if (UIP_MAX_ROUTES != 0) 244 #if (UIP_MAX_ROUTES != 0) 254 uip_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;
271 uip_ds6_route_num_routes(
void)
273 #if (UIP_MAX_ROUTES != 0) 281 uip_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)) {
339 uip_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 ");
375 LOG_INFO_6ADDR(ipaddr);
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: ");
479 LOG_INFO_6ADDR(ipaddr);
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) {
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]);
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();
591 rm_routelist_callback(nbr_table_item_t *ptr)
598 uip_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);
613 uip_ds6_defrt_head(
void)
619 uip_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 ");
636 LOG_ERR_6ADDR(ipaddr);
637 LOG_ERR_(
", out of memory\n");
640 LOG_INFO(
"Add default: adding default route to ");
641 LOG_INFO_6ADDR(ipaddr);
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);
665 if(LOG_DBG_ENABLED) {
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,
692 &defrt->ipaddr, &defrt->ipaddr);
698 if(LOG_DBG_ENABLED) {
699 assert_nbr_routes_list_sane();
704 uip_ds6_defrt_lookup(
const uip_ipaddr_t *ipaddr)
713 if(uip_ipaddr_cmp(&d->ipaddr, ipaddr)) {
721 uip_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);
751 uip_ds6_defrt_periodic(
void)
758 LOG_INFO(
"Default route periodic: defrt lifetime expired\n");
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
An entry in the default router list.
static volatile uint64_t count
Num.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void list_push(list_t list, void *item)
Add an item to the start of the list.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
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...
int stimer_expired(struct stimer *t)
Check if a timer has expired.
void * list_tail(list_t list)
Get the tail of a list.
Header file for IPv6-related data structures.
An entry in the routing table.
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
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.
Linked list manipulation routines.
void * list_head(list_t list)
Get a pointer to the first element of a list.
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_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
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.
Memory block allocation routines.
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
void list_add(list_t list, void *item)
Add an item at the end of a list.
void list_init(list_t list)
Initialize a list.
Header file for the uIP TCP/IP stack.
#define LIST(name)
Declare a linked list.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define UIP_DS6_ROUTE_STATE_TYPE
define some additional RPL related route state and neighbor callback for RPL - if not a DS6_ROUTE_STA...
Header file for routing table manipulation.
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
static uip_ds6_defrt_t * defrt
Pointer to an interface address.
Header file for the logging system
void list_remove(list_t list, void *item)
Remove a specific element from a list.
void * list_item_next(void *item)
Get the next item following this item.
#define MEMB(name, structure, num)
Declare a memory block.
int list_length(list_t list)
Get the length of a list.
The default nbr_table entry (when UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr cach...