Cleaned up the collect neighbor management code

This commit is contained in:
adamdunkels 2010-10-03 20:07:10 +00:00
parent b23a364397
commit d0579c8a81
2 changed files with 86 additions and 101 deletions

View file

@ -33,7 +33,7 @@
*
* This file is part of the Contiki operating system.
*
* $Id: collect-neighbor.c,v 1.6 2010/09/22 22:04:55 adamdunkels Exp $
* $Id: collect-neighbor.c,v 1.7 2010/10/03 20:07:10 adamdunkels Exp $
*/
/**
@ -63,7 +63,8 @@
MEMB(collect_neighbors_mem, struct collect_neighbor, MAX_COLLECT_NEIGHBORS);
static int max_time = 2400;
#define MAX_AGE 60
#define PERIODIC_INTERVAL CLOCK_SECOND * 60
#define DEBUG 0
#if DEBUG
@ -78,32 +79,22 @@ static void
periodic(void *ptr)
{
struct collect_neighbor_list *neighbor_list;
struct collect_neighbor *n, *next;
struct collect_neighbor *n;
neighbor_list = ptr;
/* Go through all collect_neighbors and remove old ones. */
for(n = list_head(neighbor_list->list); n != NULL; n = next) {
next = NULL;
if(!rimeaddr_cmp(&n->addr, &rimeaddr_null) &&
n->time < max_time) {
n->time++;
if(n->time == max_time) {
n->rtmetric = RTMETRIC_MAX;
PRINTF("%d.%d: removing old collect_neighbor %d.%d\n",
rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1],
n->addr.u8[0], n->addr.u8[1]);
rimeaddr_copy(&n->addr, &rimeaddr_null);
next = list_item_next(n);
list_remove(neighbor_list->list, n);
memb_free(&collect_neighbors_mem, n);
}
}
if(next == NULL) {
next = list_item_next(n);
/* Go through all collect_neighbors and increase their age. */
for(n = list_head(neighbor_list->list); n != NULL; n = list_item_next(n)) {
n->age++;
}
for(n = list_head(neighbor_list->list); n != NULL; n = list_item_next(n)) {
if(n->age == MAX_AGE) {
list_remove(neighbor_list->list, n);
n = list_head(neighbor_list->list);
}
}
ctimer_set(&neighbor_list->periodic, CLOCK_SECOND, periodic, neighbor_list);
ctimer_set(&neighbor_list->periodic, PERIODIC_INTERVAL,
periodic, neighbor_list);
}
/*---------------------------------------------------------------------------*/
void
@ -137,20 +128,17 @@ collect_neighbor_list_find(struct collect_neighbor_list *neighbors_list,
return NULL;
}
/*---------------------------------------------------------------------------*/
void
int
collect_neighbor_list_add(struct collect_neighbor_list *neighbors_list,
const rimeaddr_t *addr, uint8_t nrtmetric)
const rimeaddr_t *addr, uint16_t nrtmetric)
{
uint16_t rtmetric;
uint16_t le;
struct collect_neighbor *n, *max;
struct collect_neighbor *n;
PRINTF("collect_neighbor_add: adding %d.%d\n", addr->u8[0], addr->u8[1]);
/* Check if the collect_neighbor is already on the list. */
for(n = list_head(neighbors_list->list); n != NULL; n = list_item_next(n)) {
if(rimeaddr_cmp(&n->addr, &rimeaddr_null) ||
rimeaddr_cmp(&n->addr, addr)) {
if(rimeaddr_cmp(&n->addr, addr)) {
PRINTF("collect_neighbor_add: already on list %d.%d\n",
addr->u8[0], addr->u8[1]);
break;
@ -169,64 +157,63 @@ collect_neighbor_list_add(struct collect_neighbor_list *neighbors_list,
}
/* If we could not allocate memory, we try to recycle an old
collect_neighbor */
neighbor. XXX Should also look for the one with the worst
rtmetric (not link esimate). XXX Also make sure that we don't
replace a neighbor with a neighbor that has a worse metric. */
if(n == NULL) {
PRINTF("collect_neighbor_add: not on list, not allocated, recycling %d.%d\n",
addr->u8[0], addr->u8[1]);
/* Find the first unused entry or the used entry with the highest
rtmetric and highest link estimate. */
rtmetric = 0;
le = 0;
max = NULL;
uint16_t worst_rtmetric;
struct collect_neighbor *worst_neighbor;
for(n = list_head(neighbors_list->list); n != NULL; n = list_item_next(n)) {
if(!rimeaddr_cmp(&n->addr, &rimeaddr_null)) {
if(n->rtmetric > rtmetric) {
rtmetric = n->rtmetric;
le = collect_neighbor_link_estimate(n);
max = n;
} else if(n->rtmetric == rtmetric) {
if(collect_neighbor_link_estimate(n) > le) {
rtmetric = n->rtmetric;
le = collect_neighbor_link_estimate(n);
max = n;
/* PRINTF("%d: found worst collect_neighbor %d with rtmetric %d, signal %d\n",
node_id, collect_neighbors[n].nodeid, rtmetric, signal);*/
}
}
/* Find the neighbor that has the highest rtmetric. This is the
neighbor that we are least likely to be using in the
future. But we also need to make sure that the neighbor we are
currently adding is not worst than the one we would be
replacing. If so, we don't put the new neighbor on the list. */
worst_rtmetric = 0;
worst_neighbor = NULL;
for(n = list_head(neighbors_list->list);
n != NULL; n = list_item_next(n)) {
if(n->rtmetric > worst_rtmetric) {
worst_neighbor = n;
worst_rtmetric = n->rtmetric;
}
}
n = max;
/* Only add this new neighbor if its rtmetric is lower than the
one it would replace. */
if(nrtmetric < worst_rtmetric) {
n = worst_neighbor;
}
PRINTF("collect_neighbor_add: not on list, not allocated, recycling %d.%d\n",
n->addr.u8[0], n->addr.u8[1]);
}
/* PRINTF("%d: adding collect_neighbor %d with rtmetric %d, signal %d at %d\n",
node_id, collect_neighbors[n].nodeid, rtmetric, signal, n);*/
if(n != NULL) {
n->time = 0;
n->age = 0;
rimeaddr_copy(&n->addr, addr);
n->rtmetric = nrtmetric;
collect_link_estimate_new(&n->le);
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
list_t
collect_neighbor_list(struct collect_neighbor_list *neighbors_list)
{
return neighbors_list->list;
}
/*---------------------------------------------------------------------------*/
void
collect_neighbor_list_remove(struct collect_neighbor_list *neighbors_list,
const rimeaddr_t *addr)
{
struct collect_neighbor *n;
struct collect_neighbor *n = collect_neighbor_list_find(neighbors_list, addr);
for(n = list_head(neighbors_list->list); n != NULL; n = list_item_next(n)) {
if(rimeaddr_cmp(&n->addr, addr)) {
PRINTF("%d.%d: removing %d.%d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
addr->u8[0], addr->u8[1]);
rimeaddr_copy(&n->addr, &rimeaddr_null);
n->rtmetric = RTMETRIC_MAX;
list_remove(neighbors_list->list, n);
memb_free(&collect_neighbors_mem, n);
return;
}
if(n != NULL) {
list_remove(neighbors_list->list, n);
memb_free(&collect_neighbors_mem, n);
}
}
/*---------------------------------------------------------------------------*/
@ -243,15 +230,14 @@ collect_neighbor_list_best(struct collect_neighbor_list *neighbors_list)
/* PRINTF("%d: ", node_id);*/
PRINTF("collect_neighbor_best: ");
/* Find the lowest rtmetric. */
/* Find the neighbor with the lowest rtmetric + linkt estimate. */
for(n = list_head(neighbors_list->list); n != NULL; n = list_item_next(n)) {
PRINTF("%d.%d %d+%d=%d, ",
n->addr.u8[0], n->addr.u8[1],
n->rtmetric, collect_neighbor_link_estimate(n),
collect_neighbor_rtmetric(n));
if(!rimeaddr_cmp(&n->addr, &rimeaddr_null) &&
rtmetric > collect_neighbor_rtmetric_link_estimate(n)) {
if(collect_neighbor_rtmetric_link_estimate(n) < rtmetric) {
rtmetric = collect_neighbor_rtmetric_link_estimate(n);
best = n;
}
@ -297,59 +283,57 @@ collect_neighbor_list_purge(struct collect_neighbor_list *neighbors_list)
}
/*---------------------------------------------------------------------------*/
void
collect_neighbor_update_rtmetric(struct collect_neighbor *n, uint8_t rtmetric)
collect_neighbor_update_rtmetric(struct collect_neighbor *n, uint16_t rtmetric)
{
if(n != NULL) {
PRINTF("%d.%d: collect_neighbor_update %d.%d rtmetric %d\n",
rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
n->addr.u8[0], n->addr.u8[1], rtmetric);
n->rtmetric = rtmetric;
n->time = 0;
n->age = 0;
}
}
/*---------------------------------------------------------------------------*/
void
collect_neighbor_tx_fail(struct collect_neighbor *n, uint8_t num_tx)
collect_neighbor_tx_fail(struct collect_neighbor *n, uint16_t num_tx)
{
collect_link_estimate_update_tx_fail(&n->le, num_tx);
n->age = 0;
}
/*---------------------------------------------------------------------------*/
void
collect_neighbor_tx(struct collect_neighbor *n, uint8_t num_tx)
collect_neighbor_tx(struct collect_neighbor *n, uint16_t num_tx)
{
collect_link_estimate_update_tx(&n->le, num_tx);
n->time = 0;
n->age = 0;
}
/*---------------------------------------------------------------------------*/
void
collect_neighbor_rx(struct collect_neighbor *n)
{
collect_link_estimate_update_rx(&n->le);
n->time = 0;
n->age = 0;
}
/*---------------------------------------------------------------------------*/
int
uint16_t
collect_neighbor_link_estimate(struct collect_neighbor *n)
{
n->age = 0;
return collect_link_estimate(&n->le);
}
/*---------------------------------------------------------------------------*/
int
uint16_t
collect_neighbor_rtmetric_link_estimate(struct collect_neighbor *n)
{
n->age = 0;
return n->rtmetric + collect_link_estimate(&n->le);
}
/*---------------------------------------------------------------------------*/
int
uint16_t
collect_neighbor_rtmetric(struct collect_neighbor *n)
{
n->age = 0;
return n->rtmetric;
}
/*---------------------------------------------------------------------------*/
void
collect_neighbor_set_lifetime(int seconds)
{
max_time = seconds;
}
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -39,7 +39,7 @@
*
* This file is part of the Contiki operating system.
*
* $Id: collect-neighbor.h,v 1.4 2010/09/22 22:04:55 adamdunkels Exp $
* $Id: collect-neighbor.h,v 1.5 2010/10/03 20:07:10 adamdunkels Exp $
*/
/**
@ -63,19 +63,20 @@ struct collect_neighbor_list {
struct collect_neighbor {
struct collect_neighbor *next;
uint16_t time;
rimeaddr_t addr;
uint16_t rtmetric;
uint16_t age;
struct collect_link_estimate le;
};
void collect_neighbor_init(void);
list_t collect_neighbor_list(struct collect_neighbor_list *neighbor_list);
void collect_neighbor_list_new(struct collect_neighbor_list *neighbor_list);
void collect_neighbor_list_add(struct collect_neighbor_list *neighbor_list,
const rimeaddr_t *addr, uint8_t rtmetric);
int collect_neighbor_list_add(struct collect_neighbor_list *neighbor_list,
const rimeaddr_t *addr, uint16_t rtmetric);
void collect_neighbor_list_remove(struct collect_neighbor_list *neighbor_list,
const rimeaddr_t *addr);
struct collect_neighbor *collect_neighbor_list_find(struct collect_neighbor_list *neighbor_list,
@ -85,14 +86,14 @@ int collect_neighbor_list_num(struct collect_neighbor_list *neighbor_list);
struct collect_neighbor *collect_neighbor_list_get(struct collect_neighbor_list *neighbor_list, int num);
void collect_neighbor_list_purge(struct collect_neighbor_list *neighbor_list);
void collect_neighbor_update_rtmetric(struct collect_neighbor *n, uint8_t rtmetric);
void collect_neighbor_set_lifetime(int seconds);
void collect_neighbor_tx(struct collect_neighbor *n, uint8_t num_tx);
void collect_neighbor_update_rtmetric(struct collect_neighbor *n,
uint16_t rtmetric);
void collect_neighbor_tx(struct collect_neighbor *n, uint16_t num_tx);
void collect_neighbor_rx(struct collect_neighbor *n);
void collect_neighbor_tx_fail(struct collect_neighbor *n, uint8_t num_tx);
int collect_neighbor_link_estimate(struct collect_neighbor *n);
int collect_neighbor_rtmetric_link_estimate(struct collect_neighbor *n);
int collect_neighbor_rtmetric(struct collect_neighbor *n);
void collect_neighbor_tx_fail(struct collect_neighbor *n, uint16_t num_tx);
uint16_t collect_neighbor_link_estimate(struct collect_neighbor *n);
uint16_t collect_neighbor_rtmetric_link_estimate(struct collect_neighbor *n);
uint16_t collect_neighbor_rtmetric(struct collect_neighbor *n);
#endif /* __COLLECT_NEIGHBOR_H__ */