refactored the rpl-nbr-policy to be called from nbr-table module

This commit is contained in:
Joakim Eriksson 2015-09-20 21:02:30 +02:00
parent be81d1d2c6
commit 444015df67
13 changed files with 198 additions and 161 deletions

View file

@ -148,6 +148,13 @@
#define UIP_CONF_IPV6_RPL 1 #define UIP_CONF_IPV6_RPL 1
#endif /* UIP_CONF_IPV6_RPL */ #endif /* UIP_CONF_IPV6_RPL */
/* If RPL is enabled also enable the RPL NBR Policy */
#if UIP_CONF_IPV6_RPL
#ifndef NBR_TABLE_FIND_REMOVABLE
#define NBR_TABLE_FIND_REMOVABLE rpl_nbr_policy_find_removable
#endif /* NBR_TABLE_FIND_REMOVABLE */
#endif /* UIP_CONF_IPV6_RPL */
/* UIP_CONF_MAX_ROUTES specifies the maximum number of routes that each /* UIP_CONF_MAX_ROUTES specifies the maximum number of routes that each
node will be able to handle. */ node will be able to handle. */
#ifndef UIP_CONF_MAX_ROUTES #ifndef UIP_CONF_MAX_ROUTES

View file

@ -79,9 +79,11 @@ uip_ds6_neighbors_init(void)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_nbr_t * uip_ds6_nbr_t *
uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr,
uint8_t isrouter, uint8_t state) uint8_t isrouter, uint8_t state, nbr_table_reason_t reason,
void *data)
{ {
uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr); uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr
,reason, data);
if(nbr) { if(nbr) {
uip_ipaddr_copy(&nbr->ipaddr, ipaddr); uip_ipaddr_copy(&nbr->ipaddr, ipaddr);
#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER

View file

@ -86,8 +86,10 @@ typedef struct uip_ds6_nbr {
void uip_ds6_neighbors_init(void); void uip_ds6_neighbors_init(void);
/** \brief Neighbor Cache basic routines */ /** \brief Neighbor Cache basic routines */
uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr,
uint8_t isrouter, uint8_t state); const uip_lladdr_t *lladdr,
uint8_t isrouter, uint8_t state,
nbr_table_reason_t reason, void *data);
int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr);
const uip_lladdr_t *uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr); const uip_lladdr_t *uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr);
const uip_ipaddr_t *uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr); const uip_ipaddr_t *uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr);

View file

@ -348,7 +348,8 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length,
initialize this pointer with the list of routing entries that initialize this pointer with the list of routing entries that
are attached to this neighbor. */ are attached to this neighbor. */
routes = nbr_table_add_lladdr(nbr_routes, routes = nbr_table_add_lladdr(nbr_routes,
(linkaddr_t *)nexthop_lladdr); (linkaddr_t *)nexthop_lladdr,
NBR_TABLE_REASON_ROUTE, NULL);
if(routes == NULL) { if(routes == NULL) {
/* This should not happen, as we explicitly deallocated one /* This should not happen, as we explicitly deallocated one
route table entry above. */ route table entry above. */

View file

@ -188,7 +188,7 @@ parse(void)
info = nbr_table_get_from_lladdr(anti_replay_table, sender); info = nbr_table_get_from_lladdr(anti_replay_table, sender);
if(!info) { if(!info) {
info = nbr_table_add_lladdr(anti_replay_table, sender); info = nbr_table_add_lladdr(anti_replay_table, sender, NBR_TABLE_REASON_LLSEC, NULL);
if(!info) { if(!info) {
PRINTF("noncoresec: could not get nbr_table_item\n"); PRINTF("noncoresec: could not get nbr_table_item\n");
return FRAMER_FAILED; return FRAMER_FAILED;

View file

@ -122,7 +122,7 @@ phase_update(const linkaddr_t *neighbor, rtimer_clock_t time,
} else { } else {
/* No matching phase was found, so we allocate a new one. */ /* No matching phase was found, so we allocate a new one. */
if(mac_status == MAC_TX_OK && e == NULL) { if(mac_status == MAC_TX_OK && e == NULL) {
e = nbr_table_add_lladdr(nbr_phase, neighbor); e = nbr_table_add_lladdr(nbr_phase, neighbor, NBR_TABLE_REASON_MAC, NULL);
if(e) { if(e) {
e->time = time; e->time = time;
#if PHASE_DRIFT_CORRECT #if PHASE_DRIFT_CORRECT

View file

@ -47,11 +47,20 @@
static void handle_periodic_timer(void *ptr); static void handle_periodic_timer(void *ptr);
static struct ctimer periodic_timer; static struct ctimer periodic_timer;
static uint8_t initialized = 0; static uint8_t initialized = 0;
static void print_table();
#define PRINTF(...) printf(__VA_ARGS__) #define PRINTF(...) printf(__VA_ARGS__)
#else #else
#define PRINTF(...) #define PRINTF(...)
#endif #endif
/* This is the callback function that will be called when there is a
* nbr-policy active
**/
#ifdef NBR_TABLE_FIND_REMOVABLE
const linkaddr_t *NBR_TABLE_FIND_REMOVABLE(nbr_table_reason_t reason, void *data);
#endif /* NBR_TABLE_FIND_REMOVABLE */
/* List of link-layer addresses of the neighbors, used as key in the tables */ /* List of link-layer addresses of the neighbors, used as key in the tables */
typedef struct nbr_table_key { typedef struct nbr_table_key {
struct nbr_table_key *next; struct nbr_table_key *next;
@ -170,7 +179,7 @@ nbr_set_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item, int val
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static nbr_table_key_t * static nbr_table_key_t *
nbr_table_allocate(void) nbr_table_allocate(nbr_table_reason_t reason, void *data)
{ {
nbr_table_key_t *key; nbr_table_key_t *key;
int least_used_count = 0; int least_used_count = 0;
@ -179,39 +188,66 @@ nbr_table_allocate(void)
key = memb_alloc(&neighbor_addr_mem); key = memb_alloc(&neighbor_addr_mem);
if(key != NULL) { if(key != NULL) {
return key; return key;
} else { /* No more space, try to free a neighbor. } else {
* The replacement policy is the following: remove neighbor that is: #ifdef NBR_TABLE_FIND_REMOVABLE
* (1) not locked const linkaddr_t *lladdr;
* (2) used by fewest tables lladdr = NBR_TABLE_FIND_REMOVABLE(reason, data);
* (3) oldest (the list is ordered by insertion time) if(lladdr == NULL) {
* */ /* Nothing found that can be deleted - return NULL to indicate failure */
/* Get item from first key */ PRINTF("*** Not removing entry to allocate new\n");
key = list_head(nbr_table_keys); return NULL;
while(key != NULL) { } else {
int item_index = index_from_key(key); /* used least_used_key to indicate what is the least useful entry */
int locked = locked_map[item_index]; int index;
/* Never delete a locked item */ int locked;
if(!locked) { if((index = index_from_lladdr(lladdr)) != -1) {
int used = used_map[item_index]; least_used_key = key_from_index(index);
int used_count = 0; locked = locked_map[index];
/* Count how many tables are using this item */ }
while(used != 0) { /* Allow delete of locked item? */
if((used & 1) == 1) { if(least_used_key != NULL && locked) {
used_count++; PRINTF("Deleting locked item!\n");
} locked_map[index] = 0;
used >>= 1;
}
/* Find least used item */
if(least_used_key == NULL || used_count < least_used_count) {
least_used_key = key;
least_used_count = used_count;
if(used_count == 0) { /* We won't find any least used item */
break;
}
}
} }
key = list_item_next(key);
} }
#endif /* NBR_TABLE_FIND_REMOVABLE */
if(least_used_key == NULL) {
/* No more space, try to free a neighbor.
* The replacement policy is the following: remove neighbor that is:
* (1) not locked
* (2) used by fewest tables
* (3) oldest (the list is ordered by insertion time)
* */
/* Get item from first key */
key = list_head(nbr_table_keys);
while(key != NULL) {
int item_index = index_from_key(key);
int locked = locked_map[item_index];
/* Never delete a locked item */
if(!locked) {
int used = used_map[item_index];
int used_count = 0;
/* Count how many tables are using this item */
while(used != 0) {
if((used & 1) == 1) {
used_count++;
}
used >>= 1;
}
/* Find least used item */
if(least_used_key == NULL || used_count < least_used_count) {
least_used_key = key;
least_used_count = used_count;
if(used_count == 0) { /* We won't find any least used item */
break;
}
}
}
key = list_item_next(key);
}
}
if(least_used_key == NULL) { if(least_used_key == NULL) {
/* We haven't found any unlocked item, allocation fails */ /* We haven't found any unlocked item, allocation fails */
return NULL; return NULL;
@ -289,7 +325,7 @@ nbr_table_next(nbr_table_t *table, nbr_table_item_t *item)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Add a neighbor indexed with its link-layer address */ /* Add a neighbor indexed with its link-layer address */
nbr_table_item_t * nbr_table_item_t *
nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr) nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr, nbr_table_reason_t reason, void *data)
{ {
int index; int index;
nbr_table_item_t *item; nbr_table_item_t *item;
@ -303,7 +339,7 @@ nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr)
if((index = index_from_lladdr(lladdr)) == -1) { if((index = index_from_lladdr(lladdr)) == -1) {
/* Neighbor not yet in table, let's try to allocate one */ /* Neighbor not yet in table, let's try to allocate one */
key = nbr_table_allocate(); key = nbr_table_allocate(reason, data);
/* No space available for new entry */ /* No space available for new entry */
if(key == NULL) { if(key == NULL) {
@ -327,6 +363,9 @@ nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr)
memset(item, 0, table->item_size); memset(item, 0, table->item_size);
nbr_set_bit(used_map, table, item, 1); nbr_set_bit(used_map, table, item, 1);
#if DEBUG
print_table();
#endif
return item; return item;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -379,7 +418,7 @@ nbr_table_get_lladdr(nbr_table_t *table, const void *item)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if DEBUG #if DEBUG
static void static void
handle_periodic_timer(void *ptr) print_table()
{ {
int i, j; int i, j;
/* Printout all neighbors and which tables they are used in */ /* Printout all neighbors and which tables they are used in */
@ -394,6 +433,12 @@ handle_periodic_timer(void *ptr)
PRINTF("\n"); PRINTF("\n");
} }
} }
}
/*---------------------------------------------------------------------------*/
static void
handle_periodic_timer(void *ptr)
{
print_table();
ctimer_reset(&periodic_timer); ctimer_reset(&periodic_timer);
} }
#endif #endif

View file

@ -75,6 +75,17 @@ typedef struct nbr_table {
/** \brief Declaration of non-static neighbor tables */ /** \brief Declaration of non-static neighbor tables */
#define NBR_TABLE_DECLARE(name) extern nbr_table_t *name #define NBR_TABLE_DECLARE(name) extern nbr_table_t *name
typedef enum {
NBR_TABLE_REASON_UNDEFINED,
NBR_TABLE_REASON_RPL_DIO,
NBR_TABLE_REASON_RPL_DAO,
NBR_TABLE_REASON_RPL_DIS,
NBR_TABLE_REASON_ROUTE,
NBR_TABLE_REASON_IPV6_ND,
NBR_TABLE_REASON_MAC,
NBR_TABLE_REASON_LLSEC
} nbr_table_reason_t;
/** \name Neighbor tables: register and loop through table elements */ /** \name Neighbor tables: register and loop through table elements */
/** @{ */ /** @{ */
int nbr_table_register(nbr_table_t *table, nbr_table_callback *callback); int nbr_table_register(nbr_table_t *table, nbr_table_callback *callback);
@ -84,7 +95,7 @@ nbr_table_item_t *nbr_table_next(nbr_table_t *table, nbr_table_item_t *item);
/** \name Neighbor tables: add and get data */ /** \name Neighbor tables: add and get data */
/** @{ */ /** @{ */
nbr_table_item_t *nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr); nbr_table_item_t *nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr, nbr_table_reason_t reason, void *data);
nbr_table_item_t *nbr_table_get_from_lladdr(nbr_table_t *table, const linkaddr_t *lladdr); nbr_table_item_t *nbr_table_get_from_lladdr(nbr_table_t *table, const linkaddr_t *lladdr);
/** @} */ /** @} */

View file

@ -634,8 +634,9 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr)
PRINT6ADDR(addr); PRINT6ADDR(addr);
PRINTF("\n"); PRINTF("\n");
if(lladdr != NULL) { if(lladdr != NULL) {
/* Add parent in rpl_parents */ /* Add parent in rpl_parents - again this is due to DIO */
p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr); p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr,
NBR_TABLE_REASON_RPL_DIO, dio);
if(p == NULL) { if(p == NULL) {
PRINTF("RPL: rpl_add_parent p NULL\n"); PRINTF("RPL: rpl_add_parent p NULL\n");
} else { } else {
@ -1028,7 +1029,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio)
rpl_set_default_route(instance, from); rpl_set_default_route(instance, from);
if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) {
rpl_schedule_dao_immediately(instance); rpl_schedule_dao(instance);
} else { } else {
PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n");
} }
@ -1255,18 +1256,14 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p)
static int static int
add_nbr_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) add_nbr_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
{ {
/* check if it is ok to add this nbr based on this DIO */ /* add this to the neighbor cache if not already there */
if(RPL_NBR_POLICY.check_add_from_dio(from, dio)) { if(rpl_icmp6_update_nbr_table(from, NBR_TABLE_REASON_RPL_DIO, dio) == NULL) {
/* add this to the neighbor cache if not already there */ PRINTF("RPL: Out of memory, dropping DIO from ");
if(rpl_icmp6_update_nbr_table(from) == NULL) { PRINT6ADDR(from);
PRINTF("RPL: Out of memory, dropping DIO from "); PRINTF("\n");
PRINT6ADDR(from); return 0;
PRINTF("\n");
return 0;
}
return 1;
} }
return 0; return 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void

View file

@ -182,14 +182,14 @@ set16(uint8_t *buffer, int pos, uint16_t value)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
uip_ds6_nbr_t * uip_ds6_nbr_t *
rpl_icmp6_update_nbr_table(uip_ipaddr_t *from) rpl_icmp6_update_nbr_table(uip_ipaddr_t *from, nbr_table_reason_t reason, void *data)
{ {
uip_ds6_nbr_t *nbr; uip_ds6_nbr_t *nbr;
if((nbr = uip_ds6_nbr_lookup(from)) == NULL) { if((nbr = uip_ds6_nbr_lookup(from)) == NULL) {
if((nbr = uip_ds6_nbr_add(from, (uip_lladdr_t *) if((nbr = uip_ds6_nbr_add(from, (uip_lladdr_t *)
packetbuf_addr(PACKETBUF_ADDR_SENDER), packetbuf_addr(PACKETBUF_ADDR_SENDER),
0, NBR_REACHABLE)) != NULL) { 0, NBR_REACHABLE, reason, data)) != NULL) {
PRINTF("RPL: Neighbor added to neighbor cache "); PRINTF("RPL: Neighbor added to neighbor cache ");
PRINT6ADDR(from); PRINT6ADDR(from);
PRINTF(", "); PRINTF(", ");
@ -231,19 +231,18 @@ dis_input(void)
} else { } else {
#endif /* !RPL_LEAF_ONLY */ #endif /* !RPL_LEAF_ONLY */
/* Check if this neighbor should be added according to the policy. */ /* Check if this neighbor should be added according to the policy. */
if(RPL_NBR_POLICY.check_add_from_dis(&UIP_IP_BUF->srcipaddr)) { if(rpl_icmp6_update_nbr_table(&UIP_IP_BUF->srcipaddr,
/* Add this to the neighbor cache if not already there */ NBR_TABLE_REASON_RPL_DIS, NULL) == NULL) {
if(rpl_icmp6_update_nbr_table(&UIP_IP_BUF->srcipaddr) == NULL) { PRINTF("RPL: Out of Memory, not sending unicast DIO, DIS from ");
PRINTF("RPL: Out of Memory, not sending unicast DIO, DIS from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(", ");
PRINTF(", "); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTF("\n");
PRINTF("\n"); } else {
return; PRINTF("RPL: Unicast DIS, reply to sender\n");
} dio_output(instance, &UIP_IP_BUF->srcipaddr);
PRINTF("RPL: Unicast DIS, reply to sender\n"); }
dio_output(instance, &UIP_IP_BUF->srcipaddr); /* } */
}
} }
} }
} }
@ -806,18 +805,18 @@ dao_input(void)
PRINTF("RPL: adding DAO route\n"); PRINTF("RPL: adding DAO route\n");
/* Check if we should add another neighbor based on DAO. */
if(!RPL_NBR_POLICY.check_add_from_dao(&dao_sender_addr)) {
/* Do not add the neighbor. */
return;
}
/* Update and add neighbor - if no room - fail. */ /* Update and add neighbor - if no room - fail. */
if((nbr = rpl_icmp6_update_nbr_table(&dao_sender_addr)) == NULL) { if((nbr = rpl_icmp6_update_nbr_table(&dao_sender_addr, NBR_TABLE_REASON_RPL_DAO, NULL)) == NULL) {
PRINTF("RPL: Out of Memory, dropping DAO from "); PRINTF("RPL: Out of Memory, dropping DAO from ");
PRINT6ADDR(&dao_sender_addr); PRINT6ADDR(&dao_sender_addr);
PRINTF(", "); PRINTF(", ");
PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
PRINTF("\n"); PRINTF("\n");
if(flags & RPL_DAO_K_FLAG) {
/* signal the failure to add the node */
dao_ack_output(instance, &dao_sender_addr, sequence,
RPL_DAO_ACK_UNABLE_TO_ACCEPT);
}
goto discard; goto discard;
} }
@ -931,7 +930,9 @@ handle_dao_retransmission(void *ptr)
return; return;
} }
ctimer_set(&instance->dao_retransmit_timer, RPL_DAO_RETRANSMISSION_TIMEOUT, ctimer_set(&instance->dao_retransmit_timer,
RPL_DAO_RETRANSMISSION_TIMEOUT / 2 +
(random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT / 2)),
handle_dao_retransmission, parent); handle_dao_retransmission, parent);
instance->my_dao_transmissions++; instance->my_dao_transmissions++;
@ -1079,6 +1080,7 @@ dao_ack_input(void)
buffer = UIP_ICMP_PAYLOAD; buffer = UIP_ICMP_PAYLOAD;
instance_id = buffer[0];
sequence = buffer[2]; sequence = buffer[2];
status = buffer[3]; status = buffer[3];
@ -1131,7 +1133,9 @@ dao_ack_input(void)
if(nexthop == NULL) { if(nexthop == NULL) {
PRINTF("No next hop to fwd DAO ACK to\n"); PRINTF("No next hop to fwd DAO ACK to\n");
} else { } else {
PRINTF("Fwd DAO ACK\n"); PRINTF("Fwd DAO ACK to:");
PRINT6ADDR(nexthop);
PRINTF("\n");
buffer[2] = re->state.dao_seqno_in; buffer[2] = re->state.dao_seqno_in;
uip_icmp6_send(nexthop, ICMP6_RPL, RPL_CODE_DAO_ACK, 4); uip_icmp6_send(nexthop, ICMP6_RPL, RPL_CODE_DAO_ACK, 4);
} }

View file

@ -49,7 +49,7 @@
#include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6-nbr.h"
#include "net/ipv6/uip-ds6-route.h" #include "net/ipv6/uip-ds6-route.h"
#define DEBUG DEBUG_NONE #define DEBUG DEBUG_FULL
#include "net/ip/uip-debug.h" #include "net/ip/uip-debug.h"
/* /*
@ -58,14 +58,18 @@
* - max X children (nexthops) * - max X children (nexthops)
* - max Y "best parents" * - max Y "best parents"
* => at least MAX_NBRS - (Y + X + 1) free slots for other. * => at least MAX_NBRS - (Y + X + 1) free slots for other.
*
* NOTE: this policy assumes that all neighbors end up being IPv6
* neighbors and are not only MAC neighbors.
*/ */
#define MAX_CHILDREN (NBR_TABLE_MAX_NEIGHBORS - 3) #define MAX_CHILDREN (NBR_TABLE_MAX_NEIGHBORS - 3)
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
static int num_parents; /* any node that are possible parents */ static int num_parents; /* any node that are possible parents */
static int num_children; /* all children that we have as nexthop */ static int num_children; /* all children that we have as nexthop */
static int num_free; static int num_free;
static uip_ds6_nbr_t *worst_rank_nbr; /* the parent that has the worst rank */ static linkaddr_t *worst_rank_nbr; /* the parent that has the worst rank */
static rpl_rank_t worst_rank; static rpl_rank_t worst_rank;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if DEBUG == DEBUG_FULL #if DEBUG == DEBUG_FULL
@ -124,8 +128,12 @@ update_nbr(void)
parent->dag->instance != NULL && parent->dag->instance != NULL &&
(rank = parent->dag->instance->of->calculate_rank(parent, 0)) > worst_rank) { (rank = parent->dag->instance->of->calculate_rank(parent, 0)) > worst_rank) {
/* This is the worst-rank neighbor - this is a good candidate for removal */ /* This is the worst-rank neighbor - this is a good candidate for removal */
worst_rank = rank; if(uip_ds6_route_is_nexthop((uip_lladdr_t *)lladdr) == 0) {
worst_rank_nbr = nbr; worst_rank = rank;
worst_rank_nbr = lladdr;
} else {
printf("*** Can not use this as worst rank as it is a next hop\n");
}
} }
} }
@ -138,10 +146,9 @@ update_nbr(void)
if(is_used == 0) { if(is_used == 0) {
/* This neighbor is neither parent or child and can be safely removed */ /* This neighbor is neither parent or child and can be safely removed */
worst_rank_nbr = nbr; worst_rank_nbr = lladdr;
worst_rank = INFINITE_RANK; worst_rank = INFINITE_RANK;
} else if(is_used > 1) { } else if(is_used > 1) {
/* Both parent and child - this should never happen! */
PRINTF("NBR-POLICY: *** Neighbor is both child and candidate parent: "); PRINTF("NBR-POLICY: *** Neighbor is both child and candidate parent: ");
PRINTLLADDR((uip_lladdr_t *)lladdr); PRINTLLADDR((uip_lladdr_t *)lladdr);
PRINTF("\n"); PRINTF("\n");
@ -157,67 +164,36 @@ update_nbr(void)
num_free, num_children, num_parents, uip_ds6_route_num_routes()); num_free, num_children, num_parents, uip_ds6_route_num_routes());
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int
remove_worst_nbr(void)
{
/* we assume that it is possible to remove the worst parent at the moment */
if(worst_rank_nbr != NULL) {
PRINTF("Removing worst ranked nbr ");
PRINTLLADDR((uip_lladdr_t*)nbr_table_get_lladdr(ds6_neighbors, worst_rank_nbr));
PRINTF(" with rank %d\n", worst_rank);
if(uip_ds6_nbr_rm(worst_rank_nbr)) {
worst_rank_nbr = NULL;
return 1;
}
PRINTF("FAILED to remove worst ranked nbr!\n");
return 0;
}
PRINTF("FAILED to remove worst rank nbr - no found\n");
return 0;
}
/*---------------------------------------------------------------------------*/
/* Called whenever we get a unicast DIS - e.g. someone that already /* Called whenever we get a unicast DIS - e.g. someone that already
have this node in its table - since it is a unicast */ have this node in its table - since it is a unicast */
static int const linkaddr_t *
check_add_from_dis(uip_ipaddr_t *from) find_removable_dis(uip_ipaddr_t *from)
{ {
/* do a lookup to see if it is alread there - then allow add/update */
if(uip_ds6_nbr_lookup(from)) {
return 1;
}
update_nbr(); update_nbr();
if(num_free > 0) { if(num_free > 0) {
return 1; printf("num-free > 0 = %d", num_free);
printf("**** Should remove unused elements but can not... \n");
/* return 1; */
} }
if(num_children < MAX_CHILDREN) { if(num_children < MAX_CHILDREN) {
return remove_worst_nbr(); return worst_rank_nbr;
} }
return 0; return NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int const linkaddr_t *
check_add_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) find_removable_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
{ {
rpl_instance_t *instance; rpl_instance_t *instance;
rpl_rank_t rank; rpl_rank_t rank;
/* Do a lookup to see if it is already there - then allow add/update. */
if(uip_ds6_nbr_lookup(from)) {
return 1;
}
update_nbr(); update_nbr();
/* If there is room for this neighbor just add it. */
if(num_free > 0) {
return 1;
}
instance = rpl_get_instance(dio->instance_id); instance = rpl_get_instance(dio->instance_id);
if(instance == NULL || instance->current_dag == NULL) { if(instance == NULL || instance->current_dag == NULL) {
PRINTF("Did not find instance id: %d\n", dio->instance_id); PRINTF("Did not find instance id: %d\n", dio->instance_id);
return 0; return NULL;
} }
/* Add the new neighbor only if it is better than the preferred parent. */ /* Add the new neighbor only if it is better than the preferred parent. */
@ -227,38 +203,43 @@ check_add_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
PRINTF("Found better neighbor %d < %d - add to cache...\n", PRINTF("Found better neighbor %d < %d - add to cache...\n",
rank, worst_rank); rank, worst_rank);
return remove_worst_nbr(); return worst_rank_nbr;
} }
PRINTF("Found worse neighbor with new %d and old %d - NOT add to cache.\n", PRINTF("Found worse neighbor with new %d and old %d - NOT add to cache.\n",
rank, worst_rank); rank, worst_rank);
return 0; return NULL;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int const linkaddr_t *
check_add_from_dao(uip_ipaddr_t *from) find_removable_dao(uip_ipaddr_t *from)
{ {
/* Do a lookup to see if it is alread there - then allow add/update. */
if(uip_ds6_nbr_lookup(from)) {
return 1;
}
update_nbr(); update_nbr();
/* Check if this DAO sender is not yet neighbor and there is already too /* Check if this DAO sender is not yet neighbor and there is already too
many children. */ many children. */
if(num_children >= MAX_CHILDREN) { if(num_children >= MAX_CHILDREN) {
PRINTF("Can not add another child - already at max.\n"); PRINTF("Can not add another child - already at max.\n");
return 0; return NULL;
} }
/* remove the worst ranked nbr */
return 1; return worst_rank_nbr;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
const struct nbr_policy rpl_nbr_policy = { const linkaddr_t *
check_add_from_dis, rpl_nbr_policy_find_removable(nbr_table_reason_t reason,void * data) {
check_add_from_dio, /* When we get the DIO/DAO/DIS we know that UIP contains the
check_add_from_dao incoming packet */
}; switch(reason) {
case NBR_TABLE_REASON_RPL_DIO:
return find_removable_dio(&UIP_IP_BUF->srcipaddr, data);
case NBR_TABLE_REASON_RPL_DAO:
return find_removable_dao(&UIP_IP_BUF->srcipaddr);
case NBR_TABLE_REASON_RPL_DIS:
return find_removable_dis(&UIP_IP_BUF->srcipaddr);
default:
return NULL;
}
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @}*/ /** @}*/

View file

@ -270,22 +270,6 @@ typedef struct rpl_stats rpl_stats_t;
extern rpl_stats_t rpl_stats; extern rpl_stats_t rpl_stats;
#endif #endif
struct nbr_policy {
/** check if it is ok to add a nbr via UC DIS - positive => ok */
int (* check_add_from_dis)(uip_ipaddr_t *from);
int (* check_add_from_dio)(uip_ipaddr_t *from, rpl_dio_t *dio);
int (* check_add_from_dao)(uip_ipaddr_t *from);
};
#ifdef RPL_CONF_NBR_POLICY
#define RPL_NBR_POLICY RPL_CONF_NBR_POLICY
#else /* RPL_CONF_NBR_POLICY */
#define RPL_NBR_POLICY rpl_nbr_policy
#endif /* RPL_CONF_NBR_POLICY */
extern const struct nbr_policy RPL_NBR_POLICY;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* RPL macros. */ /* RPL macros. */
@ -307,7 +291,8 @@ void dao_output(rpl_parent_t *, uint8_t lifetime);
void dao_output_target(rpl_parent_t *, uip_ipaddr_t *, uint8_t lifetime); void dao_output_target(rpl_parent_t *, uip_ipaddr_t *, uint8_t lifetime);
void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t, uint8_t); void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t, uint8_t);
void rpl_icmp6_register_handlers(void); void rpl_icmp6_register_handlers(void);
uip_ds6_nbr_t *rpl_icmp6_update_nbr_table(uip_ipaddr_t *from); uip_ds6_nbr_t *rpl_icmp6_update_nbr_table(uip_ipaddr_t *from,
nbr_table_reason_t r, void *data);
/* RPL logic functions. */ /* RPL logic functions. */
void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio);

View file

@ -224,6 +224,8 @@ set_dao_lifetime_timer(rpl_instance_t *instance)
expiration_time = (clock_time_t)instance->default_lifetime * expiration_time = (clock_time_t)instance->default_lifetime *
(clock_time_t)instance->lifetime_unit * (clock_time_t)instance->lifetime_unit *
CLOCK_SECOND / 2; CLOCK_SECOND / 2;
/* make the time for the re registration be betwen 1/2 - 3/4 of lifetime */
expiration_time = expiration_time + (random_rand() % (expiration_time / 2));
PRINTF("RPL: Scheduling DAO lifetime timer %u ticks in the future\n", PRINTF("RPL: Scheduling DAO lifetime timer %u ticks in the future\n",
(unsigned)expiration_time); (unsigned)expiration_time);
ctimer_set(&instance->dao_lifetime_timer, expiration_time, ctimer_set(&instance->dao_lifetime_timer, expiration_time,