Merge pull request #460 from adamdunkels/push/routelist
IPv6 routes LRU
This commit is contained in:
commit
7b1e3d1c94
|
@ -46,12 +46,12 @@
|
||||||
so that it will be maintained along with the rest of the neighbor
|
so that it will be maintained along with the rest of the neighbor
|
||||||
tables in the system. */
|
tables in the system. */
|
||||||
NBR_TABLE(struct uip_ds6_route_neighbor_routes, nbr_routes);
|
NBR_TABLE(struct uip_ds6_route_neighbor_routes, nbr_routes);
|
||||||
|
MEMB(neighborroutememb, struct uip_ds6_route_neighbor_route, UIP_DS6_ROUTE_NB);
|
||||||
|
|
||||||
/* Each route is repressented by a uip_ds6_route_t structure and
|
/* Each route is repressented by a uip_ds6_route_t structure and
|
||||||
memory for each route is allocated from the routememb memory
|
memory for each route is allocated from the routememb memory
|
||||||
block. These routes are maintained on lists of route entries that
|
block. These routes are maintained on the routelist. */
|
||||||
are attached to each neighbor, via the nbr_routes neighbor
|
LIST(routelist);
|
||||||
table. */
|
|
||||||
MEMB(routememb, uip_ds6_route_t, UIP_DS6_ROUTE_NB);
|
MEMB(routememb, uip_ds6_route_t, UIP_DS6_ROUTE_NB);
|
||||||
|
|
||||||
/* Default routes are held on the defaultrouterlist and their
|
/* Default routes are held on the defaultrouterlist and their
|
||||||
|
@ -82,11 +82,11 @@ assert_nbr_routes_list_sane(void)
|
||||||
for(r = uip_ds6_route_head(),
|
for(r = uip_ds6_route_head(),
|
||||||
count = 0;
|
count = 0;
|
||||||
r != NULL &&
|
r != NULL &&
|
||||||
count < UIP_DS6_ROUTE_NB;
|
count < UIP_DS6_ROUTE_NB * 2;
|
||||||
r = uip_ds6_route_next(r),
|
r = uip_ds6_route_next(r),
|
||||||
count++);
|
count++);
|
||||||
|
|
||||||
if(count >= UIP_DS6_ROUTE_NB) {
|
if(count > UIP_DS6_ROUTE_NB) {
|
||||||
printf("uip-ds6-route.c: assert_nbr_routes_list_sane route list is in infinite loop\n");
|
printf("uip-ds6-route.c: assert_nbr_routes_list_sane route list is in infinite loop\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ void
|
||||||
uip_ds6_route_init(void)
|
uip_ds6_route_init(void)
|
||||||
{
|
{
|
||||||
memb_init(&routememb);
|
memb_init(&routememb);
|
||||||
|
list_init(routelist);
|
||||||
nbr_table_register(nbr_routes,
|
nbr_table_register(nbr_routes,
|
||||||
(nbr_table_callback *)rm_routelist_callback);
|
(nbr_table_callback *)rm_routelist_callback);
|
||||||
|
|
||||||
|
@ -155,7 +156,8 @@ static uip_lladdr_t *
|
||||||
uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route)
|
uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route)
|
||||||
{
|
{
|
||||||
if(route != NULL) {
|
if(route != NULL) {
|
||||||
return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes, route->routes);
|
return (uip_lladdr_t *)nbr_table_get_lladdr(nbr_routes,
|
||||||
|
route->neighbor_routes);
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -174,17 +176,7 @@ uip_ds6_route_nexthop(uip_ds6_route_t *route)
|
||||||
uip_ds6_route_t *
|
uip_ds6_route_t *
|
||||||
uip_ds6_route_head(void)
|
uip_ds6_route_head(void)
|
||||||
{
|
{
|
||||||
struct uip_ds6_route_neighbor_routes *routes;
|
return list_head(routelist);
|
||||||
|
|
||||||
routes = (struct uip_ds6_route_neighbor_routes *)nbr_table_head(nbr_routes);
|
|
||||||
if(routes != NULL) {
|
|
||||||
if(list_head(routes->route_list) == NULL) {
|
|
||||||
PRINTF("uip_ds6_route_head lead_head(nbr_route_list) is NULL\n");
|
|
||||||
}
|
|
||||||
return list_head(routes->route_list);
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
uip_ds6_route_t *
|
uip_ds6_route_t *
|
||||||
|
@ -192,18 +184,8 @@ uip_ds6_route_next(uip_ds6_route_t *r)
|
||||||
{
|
{
|
||||||
if(r != NULL) {
|
if(r != NULL) {
|
||||||
uip_ds6_route_t *n = list_item_next(r);
|
uip_ds6_route_t *n = list_item_next(r);
|
||||||
if(n != NULL) {
|
|
||||||
return n;
|
return n;
|
||||||
} else {
|
|
||||||
struct uip_ds6_route_neighbor_routes *routes;
|
|
||||||
routes = (struct uip_ds6_route_neighbor_routes *)
|
|
||||||
nbr_table_next(nbr_routes, r->routes);
|
|
||||||
if(routes != NULL) {
|
|
||||||
return list_head(routes->route_list);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -247,6 +229,15 @@ uip_ds6_route_lookup(uip_ipaddr_t *addr)
|
||||||
PRINTF("uip-ds6-route: No route found\n");
|
PRINTF("uip-ds6-route: No route found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(found_route != NULL) {
|
||||||
|
/* If we found a route, we put it at the end of the routeslist
|
||||||
|
list. The list is ordered by how recently we looked them up:
|
||||||
|
the least recently used route will be at the start of the
|
||||||
|
list. */
|
||||||
|
list_remove(routelist, found_route);
|
||||||
|
list_add(routelist, found_route);
|
||||||
|
}
|
||||||
|
|
||||||
return found_route;
|
return found_route;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -255,6 +246,7 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
||||||
uip_ipaddr_t *nexthop)
|
uip_ipaddr_t *nexthop)
|
||||||
{
|
{
|
||||||
uip_ds6_route_t *r;
|
uip_ds6_route_t *r;
|
||||||
|
struct uip_ds6_route_neighbor_route *nbrr;
|
||||||
|
|
||||||
#if DEBUG != DEBUG_NONE
|
#if DEBUG != DEBUG_NONE
|
||||||
assert_nbr_routes_list_sane();
|
assert_nbr_routes_list_sane();
|
||||||
|
@ -263,8 +255,8 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
||||||
/* Get link-layer address of next hop, make sure it is in neighbor table */
|
/* Get link-layer address of next hop, make sure it is in neighbor table */
|
||||||
const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
|
const uip_lladdr_t *nexthop_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(nexthop);
|
||||||
if(nexthop_lladdr == NULL) {
|
if(nexthop_lladdr == NULL) {
|
||||||
PRINTF("uip_ds6_route_add: neighbor link-local address unknown ");
|
PRINTF("uip_ds6_route_add: neighbor link-local address unknown for ");
|
||||||
PRINT6ADDR(ipaddr);
|
PRINT6ADDR(nexthop);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -279,7 +271,22 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
} else {
|
} else {
|
||||||
struct uip_ds6_route_neighbor_routes *routes;
|
struct uip_ds6_route_neighbor_routes *routes;
|
||||||
/* If there is no routing entry, create one */
|
/* If there is no routing entry, create one. We first need to
|
||||||
|
check if we have room for this route. If not, we remove the
|
||||||
|
least recently used one we have. */
|
||||||
|
|
||||||
|
if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) {
|
||||||
|
/* Removing the oldest route entry from the route table. The
|
||||||
|
least recently used route is the first route on the list. */
|
||||||
|
uip_ds6_route_t *oldest;
|
||||||
|
|
||||||
|
oldest = uip_ds6_route_head();
|
||||||
|
PRINTF("uip_ds6_route_add: dropping route to ");
|
||||||
|
PRINT6ADDR(&oldest->ipaddr);
|
||||||
|
PRINTF("\n");
|
||||||
|
uip_ds6_route_rm(oldest);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Every neighbor on our neighbor table holds a struct
|
/* Every neighbor on our neighbor table holds a struct
|
||||||
uip_ds6_route_neighbor_routes which holds a list of routes that
|
uip_ds6_route_neighbor_routes which holds a list of routes that
|
||||||
|
@ -301,9 +308,9 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
||||||
routes = nbr_table_add_lladdr(nbr_routes,
|
routes = nbr_table_add_lladdr(nbr_routes,
|
||||||
(rimeaddr_t *)nexthop_lladdr);
|
(rimeaddr_t *)nexthop_lladdr);
|
||||||
if(routes == NULL) {
|
if(routes == NULL) {
|
||||||
PRINTF("uip_ds6_route_add: could not allocate a neighbor table entri for new route to ");
|
/* This should not happen, as we explicitly deallocated one
|
||||||
PRINT6ADDR(ipaddr);
|
route table entry above. */
|
||||||
PRINTF(", dropping it\n");
|
PRINTF("uip_ds6_route_add: could not allocate neighbor table entry\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
LIST_STRUCT_INIT(routes, route_list);
|
LIST_STRUCT_INIT(routes, route_list);
|
||||||
|
@ -313,19 +320,30 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
||||||
r = memb_alloc(&routememb);
|
r = memb_alloc(&routememb);
|
||||||
|
|
||||||
if(r == NULL) {
|
if(r == NULL) {
|
||||||
PRINTF("uip_ds6_route_add: could not allocate memory for new route to ");
|
/* This should not happen, as we explicitly deallocated one
|
||||||
PRINT6ADDR(ipaddr);
|
route table entry above. */
|
||||||
PRINTF(", dropping it\n");
|
PRINTF("uip_ds6_route_add: could not allocate route\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_add(routelist, r);
|
||||||
|
|
||||||
|
nbrr = memb_alloc(&neighborroutememb);
|
||||||
|
if(nbrr == NULL) {
|
||||||
|
/* This should not happen, as we explicitly deallocated one
|
||||||
|
route table entry above. */
|
||||||
|
PRINTF("uip_ds6_route_add: could not allocate neighbor route list entry\n");
|
||||||
|
memb_free(&routememb, r);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nbrr->route = r;
|
||||||
/* Add the route to this neighbor */
|
/* Add the route to this neighbor */
|
||||||
list_add(routes->route_list, r);
|
list_add(routes->route_list, nbrr);
|
||||||
|
r->neighbor_routes = routes;
|
||||||
num_routes++;
|
num_routes++;
|
||||||
|
|
||||||
PRINTF("uip_ds6_route_add num %d\n", num_routes);
|
PRINTF("uip_ds6_route_add num %d\n", num_routes);
|
||||||
r->routes = routes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uip_ipaddr_copy(&(r->ipaddr), ipaddr);
|
uip_ipaddr_copy(&(r->ipaddr), ipaddr);
|
||||||
|
@ -356,23 +374,38 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
|
||||||
void
|
void
|
||||||
uip_ds6_route_rm(uip_ds6_route_t *route)
|
uip_ds6_route_rm(uip_ds6_route_t *route)
|
||||||
{
|
{
|
||||||
|
struct uip_ds6_route_neighbor_route *neighbor_route;
|
||||||
#if DEBUG != DEBUG_NONE
|
#if DEBUG != DEBUG_NONE
|
||||||
assert_nbr_routes_list_sane();
|
assert_nbr_routes_list_sane();
|
||||||
#endif /* DEBUG != DEBUG_NONE */
|
#endif /* DEBUG != DEBUG_NONE */
|
||||||
if(route != NULL && route->routes != NULL) {
|
if(route != NULL && route->neighbor_routes != NULL) {
|
||||||
|
|
||||||
PRINTF("uip_ds6_route_rm: removing route: ");
|
PRINTF("uip_ds6_route_rm: removing route: ");
|
||||||
PRINT6ADDR(&route->ipaddr);
|
PRINT6ADDR(&route->ipaddr);
|
||||||
PRINTF("\n");
|
PRINTF("\n");
|
||||||
|
|
||||||
list_remove(route->routes->route_list, route);
|
/* Remove the neighbor from the route list */
|
||||||
if(list_head(route->routes->route_list) == NULL) {
|
list_remove(routelist, route);
|
||||||
|
|
||||||
|
/* Find the corresponding neighbor_route and remove it. */
|
||||||
|
for(neighbor_route = list_head(route->neighbor_routes->route_list);
|
||||||
|
neighbor_route != NULL && neighbor_route->route != route;
|
||||||
|
neighbor_route = list_item_next(neighbor_route));
|
||||||
|
|
||||||
|
if(neighbor_route == NULL) {
|
||||||
|
PRINTF("uip_ds6_route_rm: neighbor_route was NULL for ");
|
||||||
|
uip_debug_ipaddr_print(&route->ipaddr);
|
||||||
|
PRINTF("\n");
|
||||||
|
}
|
||||||
|
list_remove(route->neighbor_routes->route_list, neighbor_route);
|
||||||
|
if(list_head(route->neighbor_routes->route_list) == NULL) {
|
||||||
/* If this was the only route using this neighbor, remove the
|
/* If this was the only route using this neighbor, remove the
|
||||||
neibhor from the table */
|
neibhor from the table */
|
||||||
PRINTF("uip_ds6_route_rm: removing neighbor too\n");
|
PRINTF("uip_ds6_route_rm: removing neighbor too\n");
|
||||||
nbr_table_remove(nbr_routes, route->routes->route_list);
|
nbr_table_remove(nbr_routes, route->neighbor_routes->route_list);
|
||||||
}
|
}
|
||||||
memb_free(&routememb, route);
|
memb_free(&routememb, route);
|
||||||
|
memb_free(&neighborroutememb, neighbor_route);
|
||||||
|
|
||||||
num_routes--;
|
num_routes--;
|
||||||
|
|
||||||
|
@ -417,10 +450,10 @@ rm_routelist(struct uip_ds6_route_neighbor_routes *routes)
|
||||||
#endif /* DEBUG != DEBUG_NONE */
|
#endif /* DEBUG != DEBUG_NONE */
|
||||||
PRINTF("uip_ds6_route_rm_routelist\n");
|
PRINTF("uip_ds6_route_rm_routelist\n");
|
||||||
if(routes != NULL && routes->route_list != NULL) {
|
if(routes != NULL && routes->route_list != NULL) {
|
||||||
uip_ds6_route_t *r;
|
struct uip_ds6_route_neighbor_route *r;
|
||||||
r = list_head(routes->route_list);
|
r = list_head(routes->route_list);
|
||||||
while(r != NULL) {
|
while(r != NULL) {
|
||||||
uip_ds6_route_rm(r);
|
uip_ds6_route_rm(r->route);
|
||||||
r = list_head(routes->route_list);
|
r = list_head(routes->route_list);
|
||||||
}
|
}
|
||||||
nbr_table_remove(nbr_routes, routes);
|
nbr_table_remove(nbr_routes, routes);
|
||||||
|
|
|
@ -107,7 +107,7 @@ typedef struct uip_ds6_route {
|
||||||
routes field point to the uip_ds6_route_neighbor_routes that
|
routes field point to the uip_ds6_route_neighbor_routes that
|
||||||
belong to the neighbor table entry that this routing table entry
|
belong to the neighbor table entry that this routing table entry
|
||||||
uses. */
|
uses. */
|
||||||
struct uip_ds6_route_neighbor_routes *routes;
|
struct uip_ds6_route_neighbor_routes *neighbor_routes;
|
||||||
uip_ipaddr_t ipaddr;
|
uip_ipaddr_t ipaddr;
|
||||||
#ifdef UIP_DS6_ROUTE_STATE_TYPE
|
#ifdef UIP_DS6_ROUTE_STATE_TYPE
|
||||||
UIP_DS6_ROUTE_STATE_TYPE state;
|
UIP_DS6_ROUTE_STATE_TYPE state;
|
||||||
|
@ -115,7 +115,12 @@ typedef struct uip_ds6_route {
|
||||||
uint8_t length;
|
uint8_t length;
|
||||||
} uip_ds6_route_t;
|
} uip_ds6_route_t;
|
||||||
|
|
||||||
|
/** \brief A neighbor route list entry, used on the
|
||||||
|
uip_ds6_route->neighbor_routes->route_list list. */
|
||||||
|
struct uip_ds6_route_neighbor_route {
|
||||||
|
struct uip_ds6_route_neighbor_route *next;
|
||||||
|
struct uip_ds6_route *route;
|
||||||
|
};
|
||||||
|
|
||||||
/** \brief An entry in the default router list */
|
/** \brief An entry in the default router list */
|
||||||
typedef struct uip_ds6_defrt {
|
typedef struct uip_ds6_defrt {
|
||||||
|
|
Loading…
Reference in a new issue