From fe30886b378a1fd730293de91e83a6c913ed4648 Mon Sep 17 00:00:00 2001 From: adamdunkels Date: Sun, 10 May 2009 21:08:01 +0000 Subject: [PATCH] Added functionality for decaying routes: when a packet is sent over a route, it is decayed. If the route is not refreshed within four packets (with the route_refresh() function, which is called when a new packet arrives), the route is dropped. A route can be decayed at most once per second --- core/net/rime/route.c | 97 ++++++++++++++++++++++++++++++++++------ core/net/rime/route.h | 9 ++-- core/net/uip-over-mesh.c | 22 ++++++--- 3 files changed, 106 insertions(+), 22 deletions(-) diff --git a/core/net/rime/route.c b/core/net/rime/route.c index 1a35d4fb8..0984b65c0 100644 --- a/core/net/rime/route.c +++ b/core/net/rime/route.c @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: route.c,v 1.14 2009/05/04 11:23:30 adamdunkels Exp $ + * $Id: route.c,v 1.15 2009/05/10 21:08:01 adamdunkels Exp $ */ /** @@ -57,15 +57,36 @@ #define NUM_RT_ENTRIES 8 #endif /* ROUTE_CONF_ENTRIES */ +#ifdef ROUTE_CONF_DECAY_THRESHOLD +#define DECAY_THRESHOLD ROUTE_CONF_DECAY_THRESHOLD +#else /* ROUTE_CONF_DECAY_THRESHOLD */ +#define DECAY_THRESHOLD 8 +#endif /* ROUTE_CONF_DECAY_THRESHOLD */ + +#ifdef ROUTE_CONF_DEFAULT_LIFETIME +#define DEFAULT_LIFETIME ROUTE_CONF_DEFAULT_LIFETIME +#else /* ROUTE_CONF_DEFAULT_LIFETIME */ +#define DEFAULT_LIFETIME 60 +#endif /* ROUTE_CONF_DEFAULT_LIFETIME */ + /* - * LRU (with respect to insertion time) list of route entries. + * List of route entries. */ LIST(route_table); MEMB(route_mem, struct route_entry, NUM_RT_ENTRIES); static struct ctimer t; -static int max_time = 60; +static int max_time = DEFAULT_LIFETIME; + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + /*---------------------------------------------------------------------------*/ static void @@ -76,8 +97,10 @@ periodic(void *ptr) for(e = list_head(route_table); e != NULL; e = e->next) { e->time++; if(e->time >= max_time) { - /* printf("Route to %d.%d dropped\n", - e->dest.u8[0], e->dest.u8[1]);*/ + PRINTF("route periodic: removing entry to %d.%d with nexthop %d.%d and cost %d\n", + e->dest.u8[0], e->dest.u8[1], + e->nexthop.u8[0], e->nexthop.u8[1], + e->cost); list_remove(route_table, e); memb_free(&route_mem, e); } @@ -97,31 +120,42 @@ route_init(void) /*---------------------------------------------------------------------------*/ int route_add(const rimeaddr_t *dest, const rimeaddr_t *nexthop, - uint8_t hop_count, uint8_t seqno) + uint8_t cost, uint8_t seqno) { struct route_entry *e; /* Avoid inserting duplicate entries. */ e = route_lookup(dest); - if(e != NULL) { - list_remove(route_table, e); + if(e != NULL && rimeaddr_cmp(&e->nexthop, nexthop)) { + list_remove(route_table, e); } else { - /* Allocate a new entry or reuse the oldest. */ + /* Allocate a new entry or reuse the oldest entry with highest cost. */ e = memb_alloc(&route_mem); if(e == NULL) { - e = list_chop(route_table); /* Remove oldest entry. */ + /* Remove oldest entry. XXX */ + e = list_chop(route_table); + PRINTF("route_add: removing entry to %d.%d with nexthop %d.%d and cost %d\n", + e->dest.u8[0], e->dest.u8[1], + e->nexthop.u8[0], e->nexthop.u8[1], + e->cost); } } rimeaddr_copy(&e->dest, dest); rimeaddr_copy(&e->nexthop, nexthop); - e->hop_count = hop_count; + e->cost = cost; e->seqno = seqno; e->time = 0; + e->decay = 0; /* New entry goes first. */ list_push(route_table, e); + PRINTF("route_add: new entry to %d.%d with nexthop %d.%d and cost %d\n", + e->dest.u8[0], e->dest.u8[1], + e->nexthop.u8[0], e->nexthop.u8[1], + e->cost); + return 0; } /*---------------------------------------------------------------------------*/ @@ -129,16 +163,25 @@ struct route_entry * route_lookup(const rimeaddr_t *dest) { struct route_entry *e; + uint8_t lowest_cost; + struct route_entry *best_entry; + lowest_cost = -1; + best_entry = NULL; + + /* Find the route with the lowest cost. */ for(e = list_head(route_table); e != NULL; e = e->next) { /* printf("route_lookup: comparing %d.%d.%d.%d with %d.%d.%d.%d\n", uip_ipaddr_to_quad(dest), uip_ipaddr_to_quad(&e->dest));*/ if(rimeaddr_cmp(dest, &e->dest)) { - return e; + if(e->cost < lowest_cost) { + best_entry = e; + lowest_cost = e->cost; + } } } - return NULL; + return best_entry; } /*---------------------------------------------------------------------------*/ void @@ -148,6 +191,34 @@ route_refresh(struct route_entry *e) /* Refresh age of route so that used routes do not get thrown out. */ e->time = 0; + e->decay = 0; + } +} +/*---------------------------------------------------------------------------*/ +void +route_decay(struct route_entry *e) +{ + /* If routes are not refreshed, they decay over time. This function + is called to decay a route. The route can only be decayed once + per second. */ + PRINTF("route_decay: time %d last %d decay %d for entry to %d.%d with nexthop %d.%d and cost %d\n", + e->time, e->time_last_decay, e->decay, + e->dest.u8[0], e->dest.u8[1], + e->nexthop.u8[0], e->nexthop.u8[1], + e->cost); + + if(e->time != e->time_last_decay) { + /* Do not decay a route too often - not more than once per second. */ + e->time_last_decay = e->time; + e->decay++; + + if(e->decay >= DECAY_THRESHOLD) { + PRINTF("route_decay: removing entry to %d.%d with nexthop %d.%d and cost %d\n", + e->dest.u8[0], e->dest.u8[1], + e->nexthop.u8[0], e->nexthop.u8[1], + e->cost); + route_remove(e); + } } } /*---------------------------------------------------------------------------*/ diff --git a/core/net/rime/route.h b/core/net/rime/route.h index 700a89f70..8e28ea34b 100644 --- a/core/net/rime/route.h +++ b/core/net/rime/route.h @@ -39,7 +39,7 @@ * * This file is part of the Contiki operating system. * - * $Id: route.h,v 1.10 2009/05/04 11:23:30 adamdunkels Exp $ + * $Id: route.h,v 1.11 2009/05/10 21:08:01 adamdunkels Exp $ */ /** @@ -59,13 +59,16 @@ struct route_entry { rimeaddr_t dest; rimeaddr_t nexthop; uint8_t seqno; - uint8_t hop_count; + uint8_t cost; uint8_t time; + + uint8_t decay; + uint8_t time_last_decay; }; void route_init(void); int route_add(const rimeaddr_t *dest, const rimeaddr_t *nexthop, - uint8_t hop_count, uint8_t seqno); + uint8_t cost, uint8_t seqno); struct route_entry *route_lookup(const rimeaddr_t *dest); void route_refresh(struct route_entry *e); void route_remove(struct route_entry *e); diff --git a/core/net/uip-over-mesh.c b/core/net/uip-over-mesh.c index 9ad8d73e3..19f04300e 100644 --- a/core/net/uip-over-mesh.c +++ b/core/net/uip-over-mesh.c @@ -28,7 +28,7 @@ * * This file is part of the Contiki operating system. * - * $Id: uip-over-mesh.c,v 1.13 2009/05/04 11:24:04 adamdunkels Exp $ + * $Id: uip-over-mesh.c,v 1.14 2009/05/10 21:08:01 adamdunkels Exp $ */ /** @@ -81,11 +81,19 @@ static void recv_data(struct unicast_conn *c, rimeaddr_t *from) { struct route_entry *e; + rimeaddr_t source; + + uip_len = packetbuf_copyto(&uip_buf[UIP_LLH_LEN]); + + source.u8[0] = BUF->srcipaddr.u8[2]; + source.u8[1] = BUF->srcipaddr.u8[3]; e = route_lookup(from); - route_refresh(e); - - uip_len = packetbuf_copyto(&uip_buf[UIP_LLH_LEN]); + if(e == NULL) { + route_add(&source, from, 10, 0); + } else { + route_refresh(e); + } /* uip_len = hc_inflate(&uip_buf[UIP_LLH_LEN], uip_len);*/ @@ -117,6 +125,7 @@ new_route(struct route_discovery_conn *c, rimeaddr_t *to) rt = route_lookup(&queued_receiver); if(rt) { + route_decay(rt); send_data(&queued_receiver); } } @@ -179,7 +188,7 @@ void uip_over_mesh_init(u16_t channels) { - printf("Our address is %d.%d (%d.%d.%d.%d)\n", + PRINTF("Our address is %d.%d (%d.%d.%d.%d)\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], uip_hostaddr.u8[0], uip_hostaddr.u8[1], uip_hostaddr.u8[2], uip_hostaddr.u8[3]); @@ -191,7 +200,7 @@ uip_over_mesh_init(u16_t channels) &trickle_call); /* Set lifetime to 10 seconds for non-refreshed routes. */ - route_set_lifetime(10); + route_set_lifetime(30); } /*---------------------------------------------------------------------------*/ u8_t @@ -257,6 +266,7 @@ uip_over_mesh_send(void) route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT); } } else { + route_decay(rt); send_data(&rt->nexthop); } return UIP_FW_OK;