diff --git a/core/contiki-default-conf.h b/core/contiki-default-conf.h index 0083f7e10..7b001bd58 100644 --- a/core/contiki-default-conf.h +++ b/core/contiki-default-conf.h @@ -148,6 +148,13 @@ #define UIP_CONF_IPV6_RPL 1 #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 node will be able to handle. */ #ifndef UIP_CONF_MAX_ROUTES diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index 5905993a5..b8666a14a 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -79,9 +79,11 @@ uip_ds6_neighbors_init(void) /*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * 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) { uip_ipaddr_copy(&nbr->ipaddr, ipaddr); #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER diff --git a/core/net/ipv6/uip-ds6-nbr.h b/core/net/ipv6/uip-ds6-nbr.h index b0dd84d4a..2f3a51d28 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -86,8 +86,10 @@ typedef struct uip_ds6_nbr { void uip_ds6_neighbors_init(void); /** \brief Neighbor Cache basic routines */ -uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, - uint8_t isrouter, uint8_t state); +uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, + 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); 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); diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 3113986a1..21ce38f64 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -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 are attached to this neighbor. */ routes = nbr_table_add_lladdr(nbr_routes, - (linkaddr_t *)nexthop_lladdr); + (linkaddr_t *)nexthop_lladdr, + NBR_TABLE_REASON_ROUTE, NULL); if(routes == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ diff --git a/core/net/llsec/noncoresec/noncoresec.c b/core/net/llsec/noncoresec/noncoresec.c index e18a7d734..860f7e613 100644 --- a/core/net/llsec/noncoresec/noncoresec.c +++ b/core/net/llsec/noncoresec/noncoresec.c @@ -188,7 +188,7 @@ parse(void) info = nbr_table_get_from_lladdr(anti_replay_table, sender); 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) { PRINTF("noncoresec: could not get nbr_table_item\n"); return FRAMER_FAILED; diff --git a/core/net/mac/phase.c b/core/net/mac/phase.c index 47b7e7cf3..d7ded2428 100644 --- a/core/net/mac/phase.c +++ b/core/net/mac/phase.c @@ -122,7 +122,7 @@ phase_update(const linkaddr_t *neighbor, rtimer_clock_t time, } else { /* No matching phase was found, so we allocate a new one. */ 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) { e->time = time; #if PHASE_DRIFT_CORRECT diff --git a/core/net/nbr-table.c b/core/net/nbr-table.c index 6b990a020..42597c598 100644 --- a/core/net/nbr-table.c +++ b/core/net/nbr-table.c @@ -47,11 +47,20 @@ static void handle_periodic_timer(void *ptr); static struct ctimer periodic_timer; static uint8_t initialized = 0; +static void print_table(); #define PRINTF(...) printf(__VA_ARGS__) #else #define PRINTF(...) #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 */ typedef struct nbr_table_key { 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 * -nbr_table_allocate(void) +nbr_table_allocate(nbr_table_reason_t reason, void *data) { nbr_table_key_t *key; int least_used_count = 0; @@ -179,39 +188,66 @@ nbr_table_allocate(void) key = memb_alloc(&neighbor_addr_mem); if(key != NULL) { return key; - } else { /* 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; - } - } + } else { +#ifdef NBR_TABLE_FIND_REMOVABLE + const linkaddr_t *lladdr; + lladdr = NBR_TABLE_FIND_REMOVABLE(reason, data); + if(lladdr == NULL) { + /* Nothing found that can be deleted - return NULL to indicate failure */ + PRINTF("*** Not removing entry to allocate new\n"); + return NULL; + } else { + /* used least_used_key to indicate what is the least useful entry */ + int index; + int locked; + if((index = index_from_lladdr(lladdr)) != -1) { + least_used_key = key_from_index(index); + locked = locked_map[index]; + } + /* Allow delete of locked item? */ + if(least_used_key != NULL && locked) { + PRINTF("Deleting locked item!\n"); + locked_map[index] = 0; } - 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) { /* We haven't found any unlocked item, allocation fails */ 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 */ 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; 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) { /* 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 */ 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); nbr_set_bit(used_map, table, item, 1); +#if DEBUG + print_table(); +#endif return item; } /*---------------------------------------------------------------------------*/ @@ -379,7 +418,7 @@ nbr_table_get_lladdr(nbr_table_t *table, const void *item) /*---------------------------------------------------------------------------*/ #if DEBUG static void -handle_periodic_timer(void *ptr) +print_table() { int i, j; /* Printout all neighbors and which tables they are used in */ @@ -394,6 +433,12 @@ handle_periodic_timer(void *ptr) PRINTF("\n"); } } +} +/*---------------------------------------------------------------------------*/ +static void +handle_periodic_timer(void *ptr) +{ + print_table(); ctimer_reset(&periodic_timer); } #endif diff --git a/core/net/nbr-table.h b/core/net/nbr-table.h index 516901fe3..cc58c2f80 100644 --- a/core/net/nbr-table.h +++ b/core/net/nbr-table.h @@ -75,6 +75,17 @@ typedef struct nbr_table { /** \brief Declaration of non-static neighbor tables */ #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 */ /** @{ */ 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 */ /** @{ */ -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); /** @} */ diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 79f83a84e..9d32c2773 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -634,8 +634,9 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) PRINT6ADDR(addr); PRINTF("\n"); if(lladdr != NULL) { - /* Add parent in rpl_parents */ - p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr); + /* Add parent in rpl_parents - again this is due to DIO */ + p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr, + NBR_TABLE_REASON_RPL_DIO, dio); if(p == NULL) { PRINTF("RPL: rpl_add_parent p NULL\n"); } else { @@ -1028,7 +1029,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_set_default_route(instance, from); if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { - rpl_schedule_dao_immediately(instance); + rpl_schedule_dao(instance); } else { 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 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 */ - if(RPL_NBR_POLICY.check_add_from_dio(from, dio)) { - /* add this to the neighbor cache if not already there */ - if(rpl_icmp6_update_nbr_table(from) == NULL) { - PRINTF("RPL: Out of memory, dropping DIO from "); - PRINT6ADDR(from); - PRINTF("\n"); - return 0; - } - return 1; + /* add this to the neighbor cache if not already there */ + if(rpl_icmp6_update_nbr_table(from, NBR_TABLE_REASON_RPL_DIO, dio) == NULL) { + PRINTF("RPL: Out of memory, dropping DIO from "); + PRINT6ADDR(from); + PRINTF("\n"); + return 0; } - return 0; + return 1; } /*---------------------------------------------------------------------------*/ void diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 5233c1fdd..83dd71897 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -182,14 +182,14 @@ set16(uint8_t *buffer, int pos, uint16_t value) } /*---------------------------------------------------------------------------*/ 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; if((nbr = uip_ds6_nbr_lookup(from)) == NULL) { if((nbr = uip_ds6_nbr_add(from, (uip_lladdr_t *) packetbuf_addr(PACKETBUF_ADDR_SENDER), - 0, NBR_REACHABLE)) != NULL) { + 0, NBR_REACHABLE, reason, data)) != NULL) { PRINTF("RPL: Neighbor added to neighbor cache "); PRINT6ADDR(from); PRINTF(", "); @@ -231,19 +231,18 @@ dis_input(void) } else { #endif /* !RPL_LEAF_ONLY */ /* Check if this neighbor should be added according to the policy. */ - if(RPL_NBR_POLICY.check_add_from_dis(&UIP_IP_BUF->srcipaddr)) { - /* Add this to the neighbor cache if not already there */ - if(rpl_icmp6_update_nbr_table(&UIP_IP_BUF->srcipaddr) == NULL) { - PRINTF("RPL: Out of Memory, not sending unicast DIO, DIS from "); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - return; - } - PRINTF("RPL: Unicast DIS, reply to sender\n"); - dio_output(instance, &UIP_IP_BUF->srcipaddr); - } + if(rpl_icmp6_update_nbr_table(&UIP_IP_BUF->srcipaddr, + NBR_TABLE_REASON_RPL_DIS, NULL) == NULL) { + PRINTF("RPL: Out of Memory, not sending unicast DIO, DIS from "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + } else { + 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"); - /* 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. */ - 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 "); PRINT6ADDR(&dao_sender_addr); PRINTF(", "); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); 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; } @@ -931,7 +930,9 @@ handle_dao_retransmission(void *ptr) 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); instance->my_dao_transmissions++; @@ -1079,6 +1080,7 @@ dao_ack_input(void) buffer = UIP_ICMP_PAYLOAD; + instance_id = buffer[0]; sequence = buffer[2]; status = buffer[3]; @@ -1131,7 +1133,9 @@ dao_ack_input(void) if(nexthop == NULL) { PRINTF("No next hop to fwd DAO ACK to\n"); } else { - PRINTF("Fwd DAO ACK\n"); + PRINTF("Fwd DAO ACK to:"); + PRINT6ADDR(nexthop); + PRINTF("\n"); buffer[2] = re->state.dao_seqno_in; uip_icmp6_send(nexthop, ICMP6_RPL, RPL_CODE_DAO_ACK, 4); } diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c index 34e67f946..51d0df8db 100644 --- a/core/net/rpl/rpl-nbr-policy.c +++ b/core/net/rpl/rpl-nbr-policy.c @@ -49,7 +49,7 @@ #include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6-route.h" -#define DEBUG DEBUG_NONE +#define DEBUG DEBUG_FULL #include "net/ip/uip-debug.h" /* @@ -58,14 +58,18 @@ * - max X children (nexthops) * - max Y "best parents" * => 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 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_children; /* all children that we have as nexthop */ 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; /*---------------------------------------------------------------------------*/ #if DEBUG == DEBUG_FULL @@ -124,8 +128,12 @@ update_nbr(void) parent->dag->instance != NULL && (rank = parent->dag->instance->of->calculate_rank(parent, 0)) > worst_rank) { /* This is the worst-rank neighbor - this is a good candidate for removal */ - worst_rank = rank; - worst_rank_nbr = nbr; + if(uip_ds6_route_is_nexthop((uip_lladdr_t *)lladdr) == 0) { + 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) { /* This neighbor is neither parent or child and can be safely removed */ - worst_rank_nbr = nbr; + worst_rank_nbr = lladdr; worst_rank = INFINITE_RANK; } else if(is_used > 1) { - /* Both parent and child - this should never happen! */ PRINTF("NBR-POLICY: *** Neighbor is both child and candidate parent: "); PRINTLLADDR((uip_lladdr_t *)lladdr); PRINTF("\n"); @@ -157,67 +164,36 @@ update_nbr(void) 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 have this node in its table - since it is a unicast */ -static int -check_add_from_dis(uip_ipaddr_t *from) +const linkaddr_t * +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(); 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) { - return remove_worst_nbr(); + return worst_rank_nbr; } - return 0; + return NULL; } /*---------------------------------------------------------------------------*/ -static int -check_add_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) +const linkaddr_t * +find_removable_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { rpl_instance_t *instance; 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(); - /* If there is room for this neighbor just add it. */ - if(num_free > 0) { - return 1; - } - instance = rpl_get_instance(dio->instance_id); if(instance == NULL || instance->current_dag == NULL) { 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. */ @@ -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", 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", rank, worst_rank); - return 0; + return NULL; } /*---------------------------------------------------------------------------*/ -static int -check_add_from_dao(uip_ipaddr_t *from) +const linkaddr_t * +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(); /* Check if this DAO sender is not yet neighbor and there is already too many children. */ if(num_children >= MAX_CHILDREN) { PRINTF("Can not add another child - already at max.\n"); - return 0; + return NULL; } - - return 1; + /* remove the worst ranked nbr */ + return worst_rank_nbr; } /*---------------------------------------------------------------------------*/ -const struct nbr_policy rpl_nbr_policy = { - check_add_from_dis, - check_add_from_dio, - check_add_from_dao -}; +const linkaddr_t * +rpl_nbr_policy_find_removable(nbr_table_reason_t reason,void * data) { + /* When we get the DIO/DAO/DIS we know that UIP contains the + 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; + } +} /*---------------------------------------------------------------------------*/ /** @}*/ diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index 0eecca0e0..017efb474 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -270,22 +270,6 @@ typedef struct rpl_stats rpl_stats_t; extern rpl_stats_t rpl_stats; #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. */ @@ -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_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t, uint8_t); 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. */ void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index ac993691d..158f5fd74 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -224,6 +224,8 @@ set_dao_lifetime_timer(rpl_instance_t *instance) expiration_time = (clock_time_t)instance->default_lifetime * (clock_time_t)instance->lifetime_unit * 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", (unsigned)expiration_time); ctimer_set(&instance->dao_lifetime_timer, expiration_time,