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 188 #if (UIP_MAX_ROUTES != 0) 190 static uip_lladdr_t *
194 return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes,
195 route->neighbor_routes);
205 #if (UIP_MAX_ROUTES != 0) 207 return uip_ds6_nbr_ipaddr_from_lladdr(uip_ds6_route_nexthop_lladdr(route));
217 uip_ds6_route_head(
void)
219 #if (UIP_MAX_ROUTES != 0) 229 #if (UIP_MAX_ROUTES != 0) 239 uip_ds6_route_is_nexthop(
const uip_ipaddr_t *
ipaddr)
241 #if (UIP_MAX_ROUTES != 0) 242 const uip_lladdr_t *lladdr;
243 lladdr = uip_ds6_nbr_lladdr_from_ipaddr(ipaddr);
249 return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL;
256 uip_ds6_route_num_routes(
void)
258 #if (UIP_MAX_ROUTES != 0) 266 uip_ds6_route_lookup(
const uip_ipaddr_t *
addr)
268 #if (UIP_MAX_ROUTES != 0) 271 uint8_t longestmatch;
273 LOG_INFO(
"Looking up route for ");
274 LOG_INFO_6ADDR(addr);
283 for(r = uip_ds6_route_head();
285 r = uip_ds6_route_next(r)) {
286 if(r->length >= longestmatch &&
287 uip_ipaddr_prefixcmp(addr, &r->ipaddr, r->length)) {
288 longestmatch = r->length;
291 if(longestmatch == 128) {
297 if(found_route != NULL) {
298 LOG_INFO(
"Found route: ");
299 LOG_INFO_6ADDR(addr);
301 LOG_INFO_6ADDR(uip_ds6_route_nexthop(found_route));
304 LOG_WARN(
"No route found\n");
307 if(found_route != NULL && found_route !=
list_head(routelist)) {
324 uip_ds6_route_add(
const uip_ipaddr_t *ipaddr, uint8_t length,
325 const uip_ipaddr_t *nexthop)
327 #if (UIP_MAX_ROUTES != 0) 331 if(LOG_DBG_ENABLED) {
332 assert_nbr_routes_list_sane();
335 if(ipaddr == NULL || nexthop == NULL) {
340 const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
341 if(nexthop_lladdr == NULL) {
342 LOG_WARN(
"Add: neighbor link-local address unknown for ");
343 LOG_WARN_6ADDR(nexthop);
351 r = uip_ds6_route_lookup(ipaddr);
353 const uip_ipaddr_t *current_nexthop;
354 current_nexthop = uip_ds6_route_nexthop(r);
355 if(current_nexthop != NULL && uip_ipaddr_cmp(nexthop, current_nexthop)) {
359 LOG_INFO(
"Add: old route for ");
360 LOG_INFO_6ADDR(ipaddr);
361 LOG_INFO_(
" found, deleting it\n");
371 if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) {
374 #if UIP_DS6_ROUTE_REMOVE_LEAST_RECENTLY_USED 382 LOG_INFO(
"Add: dropping route to ");
383 LOG_INFO_6ADDR(&oldest->ipaddr);
385 uip_ds6_route_rm(oldest);
397 routes = nbr_table_get_from_lladdr(nbr_routes,
398 (linkaddr_t *)nexthop_lladdr);
406 routes = nbr_table_add_lladdr(nbr_routes,
407 (linkaddr_t *)nexthop_lladdr,
408 NBR_TABLE_REASON_ROUTE, NULL);
412 LOG_ERR(
"Add: could not allocate neighbor table entry\n");
416 #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK 417 NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK((
const linkaddr_t *)nexthop_lladdr);
427 LOG_ERR(
"Add: could not allocate route\n");
439 LOG_ERR(
"Add: could not allocate neighbor route list entry\n");
447 r->neighbor_routes = routes;
450 LOG_INFO(
"Add: num %d\n", num_routes);
453 nbr_table_lock(nbr_routes, routes);
459 #ifdef UIP_DS6_ROUTE_STATE_TYPE 463 LOG_INFO(
"Add: adding route: ");
464 LOG_INFO_6ADDR(ipaddr);
466 LOG_INFO_6ADDR(nexthop);
468 LOG_ANNOTATE(
"#L %u 1;blue\n", nexthop->u8[
sizeof(uip_ipaddr_t) - 1]);
470 #if UIP_DS6_NOTIFICATIONS 471 call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_ADD, ipaddr, nexthop);
474 if(LOG_DBG_ENABLED) {
475 assert_nbr_routes_list_sane();
488 #if (UIP_MAX_ROUTES != 0) 491 if(LOG_DBG_ENABLED) {
492 assert_nbr_routes_list_sane();
495 if(route != NULL && route->neighbor_routes != NULL) {
497 LOG_INFO(
"Rm: removing route: ");
498 LOG_INFO_6ADDR(&route->ipaddr);
505 for(neighbor_route =
list_head(route->neighbor_routes->route_list);
506 neighbor_route != NULL && neighbor_route->route != route;
509 if(neighbor_route == NULL) {
510 LOG_INFO(
"Rm: neighbor_route was NULL for ");
511 LOG_INFO_6ADDR(&route->ipaddr);
514 list_remove(route->neighbor_routes->route_list, neighbor_route);
515 if(
list_head(route->neighbor_routes->route_list) == NULL) {
518 #if LOG_WITH_ANNOTATE 519 uip_ipaddr_t *nexthop = uip_ds6_route_nexthop(route);
520 if(nexthop != NULL) {
521 LOG_ANNOTATE(
"#L %u 0\n", nexthop->u8[
sizeof(uip_ipaddr_t) - 1]);
524 LOG_INFO(
"Rm: removing neighbor too\n");
525 nbr_table_remove(nbr_routes, route->neighbor_routes->route_list);
526 #ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK 527 NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(
528 (
const linkaddr_t *)nbr_table_get_lladdr(nbr_routes, route->neighbor_routes->route_list));
532 memb_free(&neighborroutememb, neighbor_route);
536 LOG_INFO(
"Rm: num %d\n", num_routes);
538 #if UIP_DS6_NOTIFICATIONS 539 call_route_callback(UIP_DS6_NOTIFICATION_ROUTE_RM,
540 &route->ipaddr, uip_ds6_route_nexthop(route));
544 if(LOG_DBG_ENABLED) {
545 assert_nbr_routes_list_sane();
551 #if (UIP_MAX_ROUTES != 0) 556 if(LOG_DBG_ENABLED) {
557 assert_nbr_routes_list_sane();
560 if(routes != NULL && routes->route_list != NULL) {
564 uip_ds6_route_rm(r->route);
567 nbr_table_remove(nbr_routes, routes);
570 if(LOG_DBG_ENABLED) {
571 assert_nbr_routes_list_sane();
576 rm_routelist_callback(nbr_table_item_t *ptr)
583 uip_ds6_route_rm_by_nexthop(
const uip_ipaddr_t *nexthop)
585 #if (UIP_MAX_ROUTES != 0) 587 const uip_lladdr_t *nexthop_lladdr;
590 nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
591 routes = nbr_table_get_from_lladdr(nbr_routes,
592 (linkaddr_t *)nexthop_lladdr);
593 rm_routelist(routes);
598 uip_ds6_defrt_head(
void)
604 uip_ds6_defrt_add(
const uip_ipaddr_t *ipaddr,
unsigned long interval)
608 if(LOG_DBG_ENABLED) {
609 assert_nbr_routes_list_sane();
616 LOG_INFO(
"Add default\n");
617 d = uip_ds6_defrt_lookup(ipaddr);
621 LOG_ERR(
"Add default: could not add default route to ");
622 LOG_ERR_6ADDR(ipaddr);
623 LOG_ERR_(
", out of memory\n");
626 LOG_INFO(
"Add default: adding default route to ");
627 LOG_INFO_6ADDR(ipaddr);
642 LOG_ANNOTATE(
"#L %u 1\n", ipaddr->u8[
sizeof(uip_ipaddr_t) - 1]);
644 #if UIP_DS6_NOTIFICATIONS 645 call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_ADD, ipaddr, ipaddr);
648 if(LOG_DBG_ENABLED) {
649 assert_nbr_routes_list_sane();
660 if(LOG_DBG_ENABLED) {
661 assert_nbr_routes_list_sane();
669 LOG_INFO(
"Removing default\n");
672 LOG_ANNOTATE(
"#L %u 0\n", defrt->ipaddr.u8[
sizeof(uip_ipaddr_t) - 1]);
673 #if UIP_DS6_NOTIFICATIONS 674 call_route_callback(UIP_DS6_NOTIFICATION_DEFRT_RM,
675 &defrt->ipaddr, &defrt->ipaddr);
681 if(LOG_DBG_ENABLED) {
682 assert_nbr_routes_list_sane();
687 uip_ds6_defrt_lookup(
const uip_ipaddr_t *ipaddr)
696 if(uip_ipaddr_cmp(&d->ipaddr, ipaddr)) {
704 uip_ds6_defrt_choose(
void)
714 LOG_INFO(
"Default route, IP address ");
715 LOG_INFO_6ADDR(&d->ipaddr);
717 bestnbr = uip_ds6_nbr_lookup(&d->ipaddr);
719 LOG_INFO(
"Default route found, IP address ");
720 LOG_INFO_6ADDR(&d->ipaddr);
725 LOG_INFO(
"Default route Incomplete found, IP address ");
726 LOG_INFO_6ADDR(&d->ipaddr);
734 uip_ds6_defrt_periodic(
void)
741 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.
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.
Linked list manipulation routines.
void * list_head(list_t list)
Get a pointer to the first element of a list.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
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().
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously 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.
An entry in the nbr cache.