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/ip/tcpip.c b/core/net/ip/tcpip.c index 00607ba14..09d182db3 100644 --- a/core/net/ip/tcpip.c +++ b/core/net/ip/tcpip.c @@ -644,7 +644,7 @@ tcpip_ipv6_output(void) nbr = uip_ds6_nbr_lookup(nexthop); if(nbr == NULL) { #if UIP_ND6_SEND_NA - if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { + if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE, NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) { uip_clear_buf(); return; } else { diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index b793ab9f0..e5c6167e5 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 @@ -115,7 +117,7 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, } /*---------------------------------------------------------------------------*/ -void +int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) { if(nbr != NULL) { @@ -123,9 +125,9 @@ uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) uip_packetqueue_free(&nbr->packethandle); #endif /* UIP_CONF_IPV6_QUEUE_PKT */ NEIGHBOR_STATE_CHANGED(nbr); - nbr_table_remove(ds6_neighbors, nbr); + return nbr_table_remove(ds6_neighbors, nbr); } - return; + return 0; } /*---------------------------------------------------------------------------*/ diff --git a/core/net/ipv6/uip-ds6-nbr.h b/core/net/ipv6/uip-ds6-nbr.h index 24e3f7aaf..2f3a51d28 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -86,9 +86,11 @@ 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); -void uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); +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); uip_ds6_nbr_t *uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr); diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 3f4ac81e7..043ca78d4 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -207,6 +207,19 @@ uip_ds6_route_next(uip_ds6_route_t *r) } /*---------------------------------------------------------------------------*/ int +uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr) +{ + const uip_lladdr_t *lladdr; + lladdr = uip_ds6_nbr_lladdr_from_ipaddr(ipaddr); + + if(lladdr == NULL) { + return 0; + } + + return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL; +} +/*---------------------------------------------------------------------------*/ +int uip_ds6_route_num_routes(void) { return num_routes; @@ -307,11 +320,16 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, least recently used one we have. */ if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) { + uip_ds6_route_t *oldest; + oldest = NULL; +#if UIP_DS6_ROUTE_REMOVE_LEAST_RECENTLY_USED /* 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 = list_tail(routelist); /* uip_ds6_route_head(); */ + oldest = list_tail(routelist); +#endif + if(oldest == NULL) { + return NULL; + } PRINTF("uip_ds6_route_add: dropping route to "); PRINT6ADDR(&oldest->ipaddr); PRINTF("\n"); @@ -337,7 +355,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/ipv6/uip-ds6-route.h b/core/net/ipv6/uip-ds6-route.h index 342bfeffa..6ca533c9b 100644 --- a/core/net/ipv6/uip-ds6-route.h +++ b/core/net/ipv6/uip-ds6-route.h @@ -97,11 +97,48 @@ void uip_ds6_notification_rm(struct uip_ds6_notification *n); #ifndef UIP_DS6_ROUTE_STATE_TYPE #define UIP_DS6_ROUTE_STATE_TYPE rpl_route_entry_t /* Needed for the extended route entry state when using ContikiRPL */ +#define RPL_ROUTE_ENTRY_NOPATH_RECEIVED 0x01 +#define RPL_ROUTE_ENTRY_DAO_PENDING 0x02 +#define RPL_ROUTE_ENTRY_DAO_NACK 0x04 + +#define RPL_ROUTE_IS_NOPATH_RECEIVED(route) \ + (((route)->state.state_flags & RPL_ROUTE_ENTRY_NOPATH_RECEIVED) != 0) +#define RPL_ROUTE_SET_NOPATH_RECEIVED(route) do { \ + (route)->state.state_flags |= RPL_ROUTE_ENTRY_NOPATH_RECEIVED; \ + } while(0) +#define RPL_ROUTE_CLEAR_NOPATH_RECEIVED(route) do { \ + (route)->state.state_flags &= ~RPL_ROUTE_ENTRY_NOPATH_RECEIVED; \ + } while(0) + +#define RPL_ROUTE_IS_DAO_PENDING(route) \ + ((route->state.state_flags & RPL_ROUTE_ENTRY_DAO_PENDING) != 0) +#define RPL_ROUTE_SET_DAO_PENDING(route) do { \ + (route)->state.state_flags |= RPL_ROUTE_ENTRY_DAO_PENDING; \ + } while(0) +#define RPL_ROUTE_CLEAR_DAO_PENDING(route) do { \ + (route)->state.state_flags &= ~RPL_ROUTE_ENTRY_DAO_PENDING; \ + } while(0) + +#define RPL_ROUTE_IS_DAO_NACKED(route) \ + ((route->state.state_flags & RPL_ROUTE_ENTRY_DAO_NACK) != 0) +#define RPL_ROUTE_SET_DAO_NACKED(route) do { \ + (route)->state.state_flags |= RPL_ROUTE_ENTRY_DAO_NACK; \ + } while(0) +#define RPL_ROUTE_CLEAR_DAO_NACKED(route) do { \ + (route)->state.state_flags &= ~RPL_ROUTE_ENTRY_DAO_NACK; \ + } while(0) + +#define RPL_ROUTE_CLEAR_DAO(route) do { \ + (route)->state.state_flags &= ~(RPL_ROUTE_ENTRY_DAO_NACK|RPL_ROUTE_ENTRY_DAO_PENDING); \ + } while(0) + +struct rpl_dag; typedef struct rpl_route_entry { uint32_t lifetime; - void *dag; - uint8_t learned_from; - uint8_t nopath_received; + struct rpl_dag *dag; + uint8_t dao_seqno_out; + uint8_t dao_seqno_in; + uint8_t state_flags; } rpl_route_entry_t; #endif /* UIP_DS6_ROUTE_STATE_TYPE */ @@ -166,7 +203,7 @@ uip_ipaddr_t *uip_ds6_route_nexthop(uip_ds6_route_t *); int uip_ds6_route_num_routes(void); uip_ds6_route_t *uip_ds6_route_head(void); uip_ds6_route_t *uip_ds6_route_next(uip_ds6_route_t *); - +int uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr); /** @} */ #endif /* UIP_DS6_ROUTE_H */ diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 143cfe369..107e66369 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -203,7 +203,8 @@ ns_input(void) if(nbr == NULL) { uip_lladdr_t lladdr_aligned; extract_lladdr_aligned(&lladdr_aligned); - uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); + uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, + 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], @@ -634,14 +635,16 @@ rs_input(void) extract_lladdr_aligned(&lladdr_aligned); if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) { /* we need to add the neighbor */ - uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); + uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, + 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { /* If LL address changed, set neighbor state to stale */ if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) { + uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) { uip_ds6_nbr_t nbr_data = *nbr; uip_ds6_nbr_rm(nbr); - nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); + nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, + 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); nbr->reachable = nbr_data.reachable; nbr->sendns = nbr_data.sendns; nbr->nscount = nbr_data.nscount; @@ -870,7 +873,8 @@ ra_input(void) if(nbr == NULL) { uip_lladdr_t lladdr_aligned; extract_lladdr_aligned(&lladdr_aligned); - nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE); + nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, + 1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); if(nbr->state == NBR_INCOMPLETE) { 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..ddae06fca 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 = 0; + 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..88a90a46c 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-conf.h b/core/net/rpl/rpl-conf.h index 5511b8289..6822ff550 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -118,7 +118,7 @@ #ifdef RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME #define RPL_DEFAULT_ROUTE_INFINITE_LIFETIME RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME #else -#define RPL_DEFAULT_ROUTE_INFINITE_LIFETIME 0 +#define RPL_DEFAULT_ROUTE_INFINITE_LIFETIME 1 #endif /* RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME */ /* @@ -200,7 +200,7 @@ * used in RPL lifetime values, in seconds. */ #ifndef RPL_CONF_DEFAULT_LIFETIME_UNIT -#define RPL_DEFAULT_LIFETIME_UNIT 0xffff +#define RPL_DEFAULT_LIFETIME_UNIT 0x60 #else #define RPL_DEFAULT_LIFETIME_UNIT RPL_CONF_DEFAULT_LIFETIME_UNIT #endif @@ -209,7 +209,7 @@ * Default route lifetime as a multiple of the lifetime unit. */ #ifndef RPL_CONF_DEFAULT_LIFETIME -#define RPL_DEFAULT_LIFETIME 0xff +#define RPL_DEFAULT_LIFETIME 0x30 #else #define RPL_DEFAULT_LIFETIME RPL_CONF_DEFAULT_LIFETIME #endif @@ -235,6 +235,39 @@ #define RPL_INSERT_HBH_OPTION 1 #endif +/* + * RPL DAO ACK support. When enabled, DAO ACK will be sent and requested. + * This will also enable retransmission of DAO when no ack is received. + * */ +#ifdef RPL_CONF_WITH_DAO_ACK +#define RPL_WITH_DAO_ACK RPL_CONF_WITH_DAO_ACK +#else +#define RPL_WITH_DAO_ACK 1 +#endif /* RPL_CONF_WITH_DAO_ACK */ + +/* + * RPL REPAIR ON DAO NACK. When enabled, DAO NACK will trigger a local + * repair in order to quickly find a new parent to send DAO's to. + * NOTE: this is too agressive in some cases so use with care. + * */ +#ifdef RPL_CONF_RPL_REPAIR_ON_DAO_NACK +#define RPL_REPAIR_ON_DAO_NACK RPL_CONF_RPL_REPAIR_ON_DAO_NACK +#else +#define RPL_REPAIR_ON_DAO_NACK 0 +#endif /* RPL_CONF_RPL_REPAIR_ON_DAO_NACK */ + +/* + * Setting the DIO_REFRESH_DAO_ROUTES will make RPL always increase + * the DTSN (Destination Advertisement Trigger Sequence Number) when + * sending broadcast DIO. This is to get all children to re-register + * their DAO route. + * */ +#ifdef RPL_CONF_DIO_REFRESH_DAO_ROUTES +#define RPL_DIO_REFRESH_DAO_ROUTES RPL_CONF_DIO_REFRESH_DAO_ROUTES +#else +#define RPL_DIO_REFRESH_DAO_ROUTES 0 +#endif /* RPL_CONF_DIO_REFRESH_DAO_ROUTES */ + /* * RPL probing. When enabled, probes will be sent periodically to keep * parent link estimates up to date. diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 27a534b09..27f781bdf 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 { @@ -898,6 +899,18 @@ rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) parent->dag = dag_dst; } /*---------------------------------------------------------------------------*/ +int +rpl_has_downward_route(void) +{ + int i; + for(i = 0; i < RPL_MAX_INSTANCES; ++i) { + if(instance_table[i].used && instance_table[i].has_downward_route) { + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ rpl_dag_t * rpl_get_any_dag(void) { @@ -1155,6 +1168,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) RPL_STAT(rpl_stats.global_repairs++); } + /*---------------------------------------------------------------------------*/ void rpl_local_repair(rpl_instance_t *instance) @@ -1173,7 +1187,12 @@ rpl_local_repair(rpl_instance_t *instance) } } + /* no downward route anymore */ + instance->has_downward_route = 0; + rpl_reset_dio_timer(instance); + /* Request refresh of DAO registrations next DIO */ + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); RPL_STAT(rpl_stats.local_repairs++); } @@ -1250,6 +1269,19 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) return return_value; } /*---------------------------------------------------------------------------*/ +static int +add_nbr_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) +{ + /* 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 1; +} +/*---------------------------------------------------------------------------*/ void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { @@ -1303,7 +1335,11 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) if(instance == NULL) { PRINTF("RPL: New instance detected (ID=%u): Joining...\n", dio->instance_id); - rpl_join_instance(from, dio); + if(add_nbr_from_dio(from, dio)) { + rpl_join_instance(from, dio); + } else { + PRINTF("RPL: Not joining since could not add parent\n"); + } return; } @@ -1315,6 +1351,10 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) if(dag == NULL) { #if RPL_MAX_DAG_PER_INSTANCE > 1 PRINTF("RPL: Adding new DAG to known instance.\n"); + if(!add_nbr_from_dio(from, dio)) { + PRINTF("RPL: Could not add new DAG, could not add parent\n"); + return; + } dag = rpl_add_dag(from, dio); if(dag == NULL) { PRINTF("RPL: Failed to add DAG.\n"); @@ -1363,6 +1403,11 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) * whether to keep it in the set. */ + if(!add_nbr_from_dio(from, dio)) { + PRINTF("RPL: Could not add parent based on DIO\n"); + return; + } + p = rpl_find_parent(dag, from); if(p == NULL) { previous_dag = find_parent_dag(instance, from); diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 14de349fe..0f20ddb67 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -53,6 +53,7 @@ #include "net/rpl/rpl-private.h" #include "net/packetbuf.h" #include "net/ipv6/multicast/uip-mcast6.h" +#include "random.h" #include #include @@ -76,6 +77,9 @@ static void dio_input(void); static void dao_input(void); static void dao_ack_input(void); +static void dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix, + uint8_t lifetime, uint8_t seq_no); + /* some debug callbacks useful when debugging RPL networks */ #ifdef RPL_DEBUG_DIO_INPUT void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *); @@ -99,6 +103,38 @@ UIP_ICMP6_HANDLER(dio_handler, ICMP6_RPL, RPL_CODE_DIO, dio_input); UIP_ICMP6_HANDLER(dao_handler, ICMP6_RPL, RPL_CODE_DAO, dao_input); UIP_ICMP6_HANDLER(dao_ack_handler, ICMP6_RPL, RPL_CODE_DAO_ACK, dao_ack_input); /*---------------------------------------------------------------------------*/ + +#if RPL_WITH_DAO_ACK +static uip_ds6_route_t * +find_route_entry_by_dao_ack(uint8_t seq) +{ + uip_ds6_route_t *re; + re = uip_ds6_route_head(); + while(re != NULL) { + if(re->state.dao_seqno_out == seq && RPL_ROUTE_IS_DAO_PENDING(re)) { + /* found it! */ + return re; + } + re = uip_ds6_route_next(re); + } + return NULL; +} +#endif /* RPL_WITH_DAO_ACK */ + +/* prepare for forwarding of DAO */ +static uint8_t +prepare_for_dao_fwd(uint8_t sequence, uip_ds6_route_t *rep) +{ + /* not pending - or pending but not a retransmission */ + RPL_LOLLIPOP_INCREMENT(dao_sequence); + + /* set DAO pending and sequence numbers */ + rep->state.dao_seqno_in = sequence; + rep->state.dao_seqno_out = dao_sequence; + RPL_ROUTE_SET_DAO_PENDING(rep); + return dao_sequence; +} +/*---------------------------------------------------------------------------*/ static int get_global_addr(uip_ipaddr_t *addr) { @@ -147,6 +183,34 @@ set16(uint8_t *buffer, int pos, uint16_t value) buffer[pos++] = value & 0xff; } /*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +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, reason, data)) != NULL) { + PRINTF("RPL: Neighbor added to neighbor cache "); + PRINT6ADDR(from); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + } + } + + if(nbr != NULL) { +#if UIP_ND6_SEND_NA + /* set reachable timer if we added or found the nbr entry - and update + neighbor entry to reachable to avoid sending NS/NA, etc. */ + stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); + nbr->state = NBR_REACHABLE; +#endif /* UIP_ND6_SEND_NA */ + } + return nbr; + } +/*---------------------------------------------------------------------------*/ static void dis_input(void) { @@ -170,8 +234,19 @@ dis_input(void) rpl_reset_dio_timer(instance); } else { #endif /* !RPL_LEAF_ONLY */ - PRINTF("RPL: Unicast DIS, reply to sender\n"); - dio_output(instance, &UIP_IP_BUF->srcipaddr); + /* Check if this neighbor should be added according to the policy. */ + 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); + } + /* } */ } } } @@ -218,7 +293,6 @@ dio_input(void) int i; int len; uip_ipaddr_t from; - uip_ds6_nbr_t *nbr; memset(&dio, 0, sizeof(dio)); @@ -239,32 +313,6 @@ dio_input(void) PRINT6ADDR(&from); PRINTF("\n"); - 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) { -#if UIP_ND6_SEND_NA - /* set reachable timer */ - stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); -#endif /* UIP_ND6_SEND_NA */ - PRINTF("RPL: Neighbor added to neighbor cache "); - PRINT6ADDR(&from); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - } else { - PRINTF("RPL: Out of memory, dropping DIO from "); - PRINT6ADDR(&from); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - - goto discard; - } - } else { - PRINTF("RPL: Neighbor already in neighbor cache\n"); - } - buffer_length = uip_len - uip_l3_icmp_hdr_len; /* Process the DIO base option. */ @@ -470,7 +518,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) buffer[pos++] = instance->dtsn_out; - if(uc_addr == NULL) { + if(RPL_DIO_REFRESH_DAO_ROUTES && uc_addr == NULL) { /* Request new DAO to refresh route. We do not do this for unicast DIO * in order to avoid DAO messages after a DIS-DIO update, * or upon unicast DIO probing. */ @@ -605,17 +653,13 @@ dao_input(void) int learned_from; rpl_parent_t *parent; uip_ds6_nbr_t *nbr; + int is_root; prefixlen = 0; parent = NULL; uip_ipaddr_copy(&dao_sender_addr, &UIP_IP_BUF->srcipaddr); - /* Destination Advertisement Object */ - PRINTF("RPL: Received a DAO from "); - PRINT6ADDR(&dao_sender_addr); - PRINTF("\n"); - buffer = UIP_ICMP_PAYLOAD; buffer_length = uip_len - uip_l3_icmp_hdr_len; @@ -637,6 +681,8 @@ dao_input(void) sequence = buffer[pos++]; dag = instance->current_dag; + is_root = (dag->rank == ROOT_RANK(instance)); + /* Is the DAG ID present? */ if(flags & RPL_DAO_D_FLAG) { if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) { @@ -649,8 +695,12 @@ dao_input(void) learned_from = uip_is_addr_mcast(&dao_sender_addr) ? RPL_ROUTE_FROM_MULTICAST_DAO : RPL_ROUTE_FROM_UNICAST_DAO; - PRINTF("RPL: DAO from %s\n", - learned_from == RPL_ROUTE_FROM_UNICAST_DAO? "unicast": "multicast"); + /* Destination Advertisement Object */ + PRINTF("RPL: Received a (%s) DAO with sequence number %u from ", + learned_from == RPL_ROUTE_FROM_UNICAST_DAO? "unicast": "multicast", sequence); + PRINT6ADDR(&dao_sender_addr); + PRINTF("\n"); + if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { /* Check whether this is a DAO forwarding loop. */ parent = rpl_find_parent(dag, &dao_sender_addr); @@ -723,86 +773,125 @@ dao_input(void) PRINTF("RPL: No-Path DAO received\n"); /* No-Path DAO received; invoke the route purging routine. */ if(rep != NULL && - rep->state.nopath_received == 0 && + !RPL_ROUTE_IS_NOPATH_RECEIVED(rep) && rep->length == prefixlen && uip_ds6_route_nexthop(rep) != NULL && uip_ipaddr_cmp(uip_ds6_route_nexthop(rep), &dao_sender_addr)) { PRINTF("RPL: Setting expiration timer for prefix "); PRINT6ADDR(&prefix); PRINTF("\n"); - rep->state.nopath_received = 1; + RPL_ROUTE_SET_NOPATH_RECEIVED(rep); rep->state.lifetime = RPL_NOPATH_REMOVAL_DELAY; /* We forward the incoming No-Path DAO to our parent, if we have one. */ if(dag->preferred_parent != NULL && rpl_get_parent_ipaddr(dag->preferred_parent) != NULL) { - PRINTF("RPL: Forwarding No-Path DAO to parent "); + uint8_t out_seq; + out_seq = prepare_for_dao_fwd(sequence, rep); + + PRINTF("RPL: Forwarding No-path DAO to parent - out_seq:%d", + out_seq); PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent)); PRINTF("\n"); + + buffer = UIP_ICMP_PAYLOAD; + buffer[3] = out_seq; /* add an outgoing seq no before fwd */ uip_icmp6_send(rpl_get_parent_ipaddr(dag->preferred_parent), ICMP6_RPL, RPL_CODE_DAO, buffer_length); } - if(flags & RPL_DAO_K_FLAG) { - dao_ack_output(instance, &dao_sender_addr, sequence); - } + } + /* independent if we remove or not - ACK the request */ + if(flags & RPL_DAO_K_FLAG) { + /* indicate that we accepted the no-path DAO */ + dao_ack_output(instance, &dao_sender_addr, sequence, + RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); } goto discard; } - PRINTF("RPL: adding DAO route\n"); + PRINTF("RPL: Adding DAO route\n"); - if((nbr = uip_ds6_nbr_lookup(&dao_sender_addr)) == NULL) { - if((nbr = uip_ds6_nbr_add(&dao_sender_addr, - (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER), - 0, NBR_REACHABLE)) != NULL) { -#if UIP_ND6_SEND_NA - /* set reachable timer */ - stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); -#endif /* UIP_ND6_SEND_NA */ - PRINTF("RPL: Neighbor added to neighbor cache "); - PRINT6ADDR(&dao_sender_addr); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - } else { - PRINTF("RPL: Out of Memory, dropping DAO from "); - PRINT6ADDR(&dao_sender_addr); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - goto discard; + /* Update and add neighbor - if no room - fail. */ + if((nbr = rpl_icmp6_update_nbr_table(&dao_sender_addr, NBR_TABLE_REASON_RPL_DAO, instance)) == 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, + is_root ? RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT : + RPL_DAO_ACK_UNABLE_TO_ACCEPT); } - } else { - PRINTF("RPL: Neighbor already in neighbor cache\n"); + goto discard; } rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr); if(rep == NULL) { RPL_STAT(rpl_stats.mem_overflows++); PRINTF("RPL: Could not add a route after receiving a DAO\n"); + if(flags & RPL_DAO_K_FLAG) { + /* signal the failure to add the node */ + dao_ack_output(instance, &dao_sender_addr, sequence, + is_root ? RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT : + RPL_DAO_ACK_UNABLE_TO_ACCEPT); + } goto discard; } + /* set lifetime and clear NOPATH bit */ rep->state.lifetime = RPL_LIFETIME(instance, lifetime); - rep->state.learned_from = learned_from; - rep->state.nopath_received = 0; + RPL_ROUTE_CLEAR_NOPATH_RECEIVED(rep); #if RPL_CONF_MULTICAST fwd_dao: #endif if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { + int should_ack = 0; + + if(flags & RPL_DAO_K_FLAG) { + /* + * check if this route is already installed and we can ack now! + * not pending - and same seq-no means that we can ack. + * (e.g. the route is installed already so it will not take any + * more room that it already takes - so should be ok!) + */ + if((!RPL_ROUTE_IS_DAO_PENDING(rep) && + rep->state.dao_seqno_in == sequence) || + dag->rank == ROOT_RANK(instance)) { + should_ack = 1; + } + } + if(dag->preferred_parent != NULL && rpl_get_parent_ipaddr(dag->preferred_parent) != NULL) { + uint8_t out_seq = 0; + /* if this is pending and we get the same seq no it is a retrans */ + if(RPL_ROUTE_IS_DAO_PENDING(rep) && + rep->state.dao_seqno_in == sequence) { + /* keep the same seq-no as before for parent also */ + out_seq = rep->state.dao_seqno_out; + } else { + out_seq = prepare_for_dao_fwd(sequence, rep); + } + PRINTF("RPL: Forwarding DAO to parent "); PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent)); - PRINTF("\n"); + PRINTF(" in seq: %d out seq: %d\n", sequence, out_seq); + + buffer = UIP_ICMP_PAYLOAD; + buffer[3] = out_seq; /* add an outgoing seq no before fwd */ uip_icmp6_send(rpl_get_parent_ipaddr(dag->preferred_parent), ICMP6_RPL, RPL_CODE_DAO, buffer_length); } - if(flags & RPL_DAO_K_FLAG) { - dao_ack_output(instance, &dao_sender_addr, sequence); + + if(should_ack) { + PRINTF("RPL: Sending DAO ACK\n"); + dao_ack_output(instance, &dao_sender_addr, sequence, + RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); } } @@ -810,6 +899,61 @@ fwd_dao: uip_clear_buf(); } /*---------------------------------------------------------------------------*/ +#if RPL_WITH_DAO_ACK +static void +handle_dao_retransmission(void *ptr) +{ + rpl_parent_t *parent; + uip_ipaddr_t prefix; + rpl_instance_t *instance; + + parent = ptr; + if(parent == NULL || parent->dag == NULL || parent->dag->instance == NULL) { + return; + } + instance = parent->dag->instance; + + if(instance->my_dao_transmissions >= RPL_DAO_MAX_RETRANSMISSIONS) { + /* No more retransmissions - give up. */ + if(instance->lifetime_unit == 0xffff && instance->default_lifetime == 0xff) { + /* + * ContikiRPL was previously using infinite lifetime for routes + * and no DAO_ACK configured. This probably means that the root + * and possibly other nodes might be running an old version that + * does not support DAO ack. Assume that everything is ok for + * now and let the normal repair mechanisms detect any problems. + */ + return; + } + + if(instance->of->dao_ack_callback) { + /* Inform the objective function about the timeout. */ + instance->of->dao_ack_callback(parent, RPL_DAO_ACK_TIMEOUT); + } + + /* Perform local repair and hope to find another parent. */ + rpl_local_repair(instance); + return; + } + + PRINTF("Should retransmit DAO - seq:%d trans:%d\n", instance->my_dao_seqno, + instance->my_dao_transmissions); + + if(get_global_addr(&prefix) == 0) { + return; + } + + 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++; + dao_output_target_seq(parent, &prefix, + instance->default_lifetime, instance->my_dao_seqno); +} +#endif /* RPL_WITH_DAO_ACK */ +/*---------------------------------------------------------------------------*/ void dao_output(rpl_parent_t *parent, uint8_t lifetime) { @@ -821,12 +965,43 @@ dao_output(rpl_parent_t *parent, uint8_t lifetime) return; } + if(parent == NULL || parent->dag == NULL || parent->dag->instance == NULL) { + return; + } + +#if RPL_WITH_DAO_ACK + /* set up the state since this will be the first transmission of DAO */ + /* retransmissions will call directly to dao_output_target_seq */ + /* keep track of my own sending of DAO for handling ack and loss of ack */ + if(lifetime != RPL_ZERO_LIFETIME) { + rpl_instance_t *instance; + instance = parent->dag->instance; + + instance->my_dao_seqno = dao_sequence; + instance->my_dao_transmissions = 1; + ctimer_set(&instance->dao_retransmit_timer, RPL_DAO_RETRANSMISSION_TIMEOUT, + handle_dao_retransmission, parent); + } +#else + /* We know that we have tried to register so now we are assuming + that we have a down-link - unless this is a zero lifetime one */ + parent->dag->instance->has_downward_route = lifetime != RPL_ZERO_LIFETIME; +#endif /* RPL_WITH_DAO_ACK */ + /* Sending a DAO with own prefix as target */ dao_output_target(parent, &prefix, lifetime); } /*---------------------------------------------------------------------------*/ void dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) +{ + RPL_LOLLIPOP_INCREMENT(dao_sequence); + dao_output_target_seq(parent, prefix, lifetime, dao_sequence); +} +/*---------------------------------------------------------------------------*/ +static void +dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix, + uint8_t lifetime, uint8_t seq_no) { rpl_dag_t *dag; rpl_instance_t *instance; @@ -867,8 +1042,6 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) #endif buffer = UIP_ICMP_PAYLOAD; - - RPL_LOLLIPOP_INCREMENT(dao_sequence); pos = 0; buffer[pos++] = instance->instance_id; @@ -876,12 +1049,12 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) #if RPL_DAO_SPECIFY_DAG buffer[pos] |= RPL_DAO_D_FLAG; #endif /* RPL_DAO_SPECIFY_DAG */ -#if RPL_CONF_DAO_ACK +#if RPL_WITH_DAO_ACK buffer[pos] |= RPL_DAO_K_FLAG; -#endif /* RPL_CONF_DAO_ACK */ +#endif /* RPL_WITH_DAO_ACK */ ++pos; buffer[pos++] = 0; /* reserved */ - buffer[pos++] = dao_sequence; + buffer[pos++] = seq_no; #if RPL_DAO_SPECIFY_DAG memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id)); pos+=sizeof(dag->dag_id); @@ -904,7 +1077,8 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) buffer[pos++] = 0; /* path seq - ignored */ buffer[pos++] = lifetime; - PRINTF("RPL: Sending %sDAO with prefix ", lifetime == RPL_ZERO_LIFETIME ? "No-Path " : ""); + PRINTF("RPL: Sending a %sDAO with sequence number %u, lifetime %u, prefix ", + lifetime == RPL_ZERO_LIFETIME ? "No-Path " : "", seq_no, lifetime); PRINT6ADDR(prefix); PRINTF(" to "); PRINT6ADDR(rpl_get_parent_ipaddr(parent)); @@ -918,41 +1092,113 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) static void dao_ack_input(void) { -#if DEBUG - unsigned char *buffer; +#if RPL_WITH_DAO_ACK + + uint8_t *buffer; + uint8_t instance_id; uint8_t sequence; uint8_t status; + rpl_instance_t *instance; + rpl_parent_t *parent; buffer = UIP_ICMP_PAYLOAD; + instance_id = buffer[0]; sequence = buffer[2]; status = buffer[3]; - PRINTF("RPL: Received a DAO ACK with sequence number %d and status %d from ", - sequence, status); + instance = rpl_get_instance(instance_id); + if(instance == NULL) { + uip_clear_buf(); + return; + } + + parent = rpl_find_parent(instance->current_dag, &UIP_IP_BUF->srcipaddr); + if(parent == NULL) { + /* not a known instance - drop the packet and ignore */ + uip_clear_buf(); + return; + } + + PRINTF("RPL: Received a DAO %s with sequence number %d (%d) and status %d from ", + status < 128 ? "ACK" : "NACK", + sequence, instance->my_dao_seqno, status); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); -#endif /* DEBUG */ + + if(sequence == instance->my_dao_seqno) { + instance->has_downward_route = status < 128; + + /* always stop the retransmit timer when the ACK arrived */ + ctimer_stop(&instance->dao_retransmit_timer); + + /* Inform objective function on status of the DAO ACK */ + if(instance->of->dao_ack_callback) { + instance->of->dao_ack_callback(parent, status); + } + +#if RPL_REPAIR_ON_DAO_NACK + if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) { + /* + * Failed the DAO transmission - need to remove the default route. + * Trigger a local repair since we can not get our DAO in. + */ + rpl_local_repair(instance); + } +#endif + + } else { + /* this DAO ACK should be forwarded to another recently registered route */ + uip_ds6_route_t *re; + uip_ipaddr_t *nexthop; + if((re = find_route_entry_by_dao_ack(sequence)) != NULL) { + /* pick the recorded seq no from that node and forward DAO ACK - and + clear the pending flag*/ + RPL_ROUTE_CLEAR_DAO_PENDING(re); + + nexthop = uip_ds6_route_nexthop(re); + if(nexthop == NULL) { + PRINTF("RPL: No next hop to fwd DAO ACK to\n"); + } else { + PRINTF("RPL: 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); + } + + if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) { + /* this node did not get in to the routing tables above... - remove */ + uip_ds6_route_rm(re); + } + } else { + PRINTF("RPL: No route entry to fwd DAO ACK to\n"); + } + } +#endif /* RPL_WITH_DAO_ACK */ uip_clear_buf(); } /*---------------------------------------------------------------------------*/ void -dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence) +dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence, + uint8_t status) { +#if RPL_WITH_DAO_ACK unsigned char *buffer; - PRINTF("RPL: Sending a DAO ACK with sequence number %d to ", sequence); + PRINTF("RPL: Sending a DAO %s with sequence number %d to ", status < 128 ? "ACK" : "NACK", sequence); PRINT6ADDR(dest); - PRINTF("\n"); + PRINTF(" with status %d\n", status); buffer = UIP_ICMP_PAYLOAD; buffer[0] = instance->instance_id; buffer[1] = 0; buffer[2] = sequence; - buffer[3] = 0; + buffer[3] = status; uip_icmp6_send(dest, ICMP6_RPL, RPL_CODE_DAO_ACK, 4); +#endif /* RPL_WITH_DAO_ACK */ } /*---------------------------------------------------------------------------*/ void diff --git a/core/net/rpl/rpl-mrhof.c b/core/net/rpl/rpl-mrhof.c index 47314917f..f9ea76080 100644 --- a/core/net/rpl/rpl-mrhof.c +++ b/core/net/rpl/rpl-mrhof.c @@ -54,6 +54,9 @@ static void reset(rpl_dag_t *); static void neighbor_link_callback(rpl_parent_t *, int, int); +#if RPL_WITH_DAO_ACK +static void dao_ack_callback(rpl_parent_t *, int); +#endif static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t); @@ -62,6 +65,9 @@ static void update_metric_container(rpl_instance_t *); rpl_of_t rpl_mrhof = { reset, neighbor_link_callback, +#if RPL_WITH_DAO_ACK + dao_ack_callback, +#endif best_parent, best_dag, calculate_rank, @@ -117,6 +123,25 @@ reset(rpl_dag_t *dag) PRINTF("RPL: Reset MRHOF\n"); } +#if RPL_WITH_DAO_ACK +static void +dao_ack_callback(rpl_parent_t *p, int status) +{ + if(status == RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT) { + return; + } + /* here we need to handle failed DAO's and other stuff */ + PRINTF("RPL: MRHOF - DAO ACK received with status: %d\n", status); + if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) { + /* punish the ETX as if this was 10 packets lost */ + neighbor_link_callback(p, MAC_TX_OK, 10); + } else if(status == RPL_DAO_ACK_TIMEOUT) { /* timeout = no ack */ + /* punish the total lack of ACK with a similar punishment */ + neighbor_link_callback(p, MAC_TX_OK, 10); + } +} +#endif /* RPL_WITH_DAO_ACK */ + static void neighbor_link_callback(rpl_parent_t *p, int status, int numtx) { diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c new file mode 100644 index 000000000..87849af40 --- /dev/null +++ b/core/net/rpl/rpl-nbr-policy.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2014-2015, Yanzi Networks AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup uip6 + * @{ + */ + + +/** + * \file + * + * Default RPL NBR policy + * decides when to add a new discovered node to the nbr table from RPL. + * + * \author Joakim Eriksson + * Contributors: Niclas Finne , Oriol PiƱol , + * + */ + +#include "net/rpl/rpl-private.h" +#include "net/nbr-table.h" +#include "net/ipv6/uip-ds6-nbr.h" +#include "net/ipv6/uip-ds6-route.h" + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +/* + * Policy for neighbor adds + * - one node is locked (default route) + * - 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 - 2) +#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 linkaddr_t *worst_rank_nbr; /* the parent that has the worst rank */ +static rpl_rank_t worst_rank; +/*---------------------------------------------------------------------------*/ +#if DEBUG == DEBUG_FULL +/* + * This create a periodic call of the update_nbr function that will print + * useful debugging information when in DEBUG_FULL mode + */ +static void update_nbr(void); +static struct ctimer periodic_timer; +static int timer_init = 0; +static void +handle_periodic_timer(void *ptr) +{ + update_nbr(); + ctimer_restart(&periodic_timer); +} +#endif /* DEBUG == DEBUG_FULL */ +/*---------------------------------------------------------------------------*/ +static void +update_nbr(void) +{ + uip_ds6_nbr_t *nbr; + rpl_parent_t *parent; + int num_used; + int is_used; + rpl_rank_t rank; + +#if DEBUG == DEBUG_FULL + if(!timer_init) { + timer_init = 1; + ctimer_set(&periodic_timer, 60 * CLOCK_SECOND, + &handle_periodic_timer, NULL); + } +#endif /* DEBUG == DEBUG_FULL */ + + worst_rank = 0; + worst_rank_nbr = NULL; + num_used = 0; + num_parents = 0; + num_children = 0; + + nbr = nbr_table_head(ds6_neighbors); + while(nbr != NULL) { + linkaddr_t *lladdr = nbr_table_get_lladdr(ds6_neighbors, nbr); + is_used = 0; + + /* + * Check if this neighbor is used as nexthop and therefor being a + * RPL child. + */ + + if(uip_ds6_route_is_nexthop(&nbr->ipaddr) != 0) { + is_used++; + num_children++; + } + + parent = rpl_get_parent((uip_lladdr_t *)lladdr); + if(parent != NULL) { + num_parents++; + + if(parent->dag != NULL && parent->dag->preferred_parent == parent) { + /* + * This is the preferred parent for the DAG and must not be removed + * Note: this assumes that only RPL adds default routes. + */ + } else if(is_used == 0 && worst_rank < INFINITE_RANK && + parent->rank > 0 && + parent->dag != NULL && + 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 = lladdr; + } + /* add to is_used after evaluation of is_used above */ + is_used++; + } + + if(is_used == 0) { + /* This neighbor is neither parent or child and can be safely removed */ + worst_rank_nbr = lladdr; + worst_rank = INFINITE_RANK; + } else if(is_used > 1) { + PRINTF("NBR-POLICY: *** Neighbor is both child and candidate parent: "); + PRINTLLADDR((uip_lladdr_t *)lladdr); + PRINTF("\n"); + } + + nbr = nbr_table_next(ds6_neighbors, nbr); + num_used++; + } + /* how many more IP neighbors can be have? */ + num_free = NBR_TABLE_MAX_NEIGHBORS - num_used; + + PRINTF("NBR-POLICY: Free: %d, Children: %d, Parents: %d Routes: %d\n", + num_free, num_children, num_parents, uip_ds6_route_num_routes()); +} +/*---------------------------------------------------------------------------*/ +/* Called whenever we get a unicast DIS - e.g. someone that already + have this node in its table - since it is a unicast */ +const linkaddr_t * +find_removable_dis(uip_ipaddr_t *from) +{ + + update_nbr(); + if(num_free > 0) { + /* there are free entries (e.g. unsused by RPL and ND6) but since it is + used by other modules we can not pick these entries for removal. */ + PRINTF("Num-free > 0 = %d - Other for RPL/ND6 unused NBR entry exists .", + num_free); + } + if(num_children < MAX_CHILDREN) { + return worst_rank_nbr; + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +const linkaddr_t * +find_removable_dio(uip_ipaddr_t *from, rpl_dio_t *dio) +{ + rpl_instance_t *instance; + rpl_rank_t rank; + + update_nbr(); + + 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 NULL; + } + + /* Add the new neighbor only if it is better than the worst parent. */ + rank = instance->of->calculate_rank(NULL, dio->rank); + if(rank < worst_rank - instance->min_hoprankinc / 2) { + /* Found *great* neighbor - add! */ + PRINTF("Found better neighbor %d < %d - add to cache...\n", + rank, worst_rank); + + return worst_rank_nbr; + } + + PRINTF("Found worse neighbor with new %d and old %d - NOT add to cache.\n", + rank, worst_rank); + return NULL; +} +/*---------------------------------------------------------------------------*/ +const linkaddr_t * +find_removable_dao(uip_ipaddr_t *from, rpl_instance_t *instance) +{ + int max = MAX_CHILDREN; + update_nbr(); + + if(instance != NULL) { + /* No need to reserve space for parents for RPL ROOT */ + if(instance->current_dag->rank == ROOT_RANK(instance)) { + max = NBR_TABLE_MAX_NEIGHBORS; + } + } + + /* Check if this DAO sender is not yet neighbor and there is already too + many children. */ + if(num_children >= max) { + PRINTF("Can not add another child - already at max.\n"); + return NULL; + } + /* remove the worst ranked nbr */ + return worst_rank_nbr; +} +/*---------------------------------------------------------------------------*/ +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, data); + case NBR_TABLE_REASON_RPL_DIS: + return find_removable_dis(&UIP_IP_BUF->srcipaddr); + default: + return NULL; + } +} +/*---------------------------------------------------------------------------*/ +/** @}*/ diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index ca73169fc..b0a909a4d 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -55,6 +55,9 @@ static void update_metric_container(rpl_instance_t *); rpl_of_t rpl_of0 = { reset, NULL, +#if RPL_WITH_DAO_ACK + NULL, +#endif best_parent, best_dag, calculate_rank, diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index e1d95697b..ec885eaea 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -90,6 +90,14 @@ #define RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */ #define RPL_DAO_D_FLAG 0x40 /* DODAG ID present */ + +#define RPL_DAO_ACK_UNCONDITIONAL_ACCEPT 0 +#define RPL_DAO_ACK_ACCEPT 1 /* 1 - 127 is OK but not good */ +#define RPL_DAO_ACK_UNABLE_TO_ACCEPT 128 /* >127 is fail */ +#define RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT 255 /* root can not accept */ + +#define RPL_DAO_ACK_TIMEOUT -1 + /*---------------------------------------------------------------------------*/ /* RPL IPv6 extension header option. */ #define RPL_HDR_OPT_LEN 4 @@ -117,6 +125,18 @@ #define RPL_NOPATH_REMOVAL_DELAY 60 #endif /* RPL_CONF_NOPATH_REMOVAL_DELAY */ +#ifdef RPL_CONF_DAO_MAX_RETRANSMISSIONS +#define RPL_DAO_MAX_RETRANSMISSIONS RPL_CONF_DAO_MAX_RETRANSMISSIONS +#else +#define RPL_DAO_MAX_RETRANSMISSIONS 5 +#endif /* RPL_CONF_DAO_MAX_RETRANSMISSIONS */ + +#ifdef RPL_CONF_DAO_RETRANSMISSION_TIMEOUT +#define RPL_DAO_RETRANSMISSION_TIMEOUT RPL_CONF_DAO_RETRANSMISSION_TIMEOUT +#else +#define RPL_DAO_RETRANSMISSION_TIMEOUT (5 * CLOCK_SECOND) +#endif /* RPL_CONF_DAO_RETRANSMISSION_TIMEOUT */ + /* Special value indicating immediate removal. */ #define RPL_ZERO_LIFETIME 0 @@ -250,6 +270,8 @@ typedef struct rpl_stats rpl_stats_t; extern rpl_stats_t rpl_stats; #endif + + /*---------------------------------------------------------------------------*/ /* RPL macros. */ @@ -268,8 +290,10 @@ void dis_output(uip_ipaddr_t *addr); void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr); 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); +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, + 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, diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 7e7947e34..c541463d4 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -238,7 +238,8 @@ rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, rep->state.dag = dag; rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime); - rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL; + /* always clear state flags for the no-path received when adding/refreshing */ + RPL_ROUTE_CLEAR_NOPATH_RECEIVED(rep); PRINTF("RPL: Added a route to "); PRINT6ADDR(prefix); diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 54b63c875..532df4b3a 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -181,10 +181,19 @@ typedef struct rpl_instance rpl_instance_t; * Updates the metric container for outgoing DIOs in a certain DAG. * If the objective function of the DAG does not use metric containers, * the function should set the object type to RPL_DAG_MC_NONE. + * + * dao_ack_callback(parent, status) + * + * A callback on the result of the DAO ACK. Similar to the neighbor link + * callback. A failed DAO_ACK (NACK) can be used for switching to another + * parent via changed link metric or other mechanisms. */ struct rpl_of { void (*reset)(struct rpl_dag *); void (*neighbor_link_callback)(rpl_parent_t *, int, int); +#if RPL_WITH_DAO_ACK + void (*dao_ack_callback)(rpl_parent_t *, int status); +#endif rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *); rpl_dag_t *(*best_dag)(rpl_dag_t *, rpl_dag_t *); rpl_rank_t (*calculate_rank)(rpl_parent_t *, rpl_rank_t); @@ -216,6 +225,11 @@ struct rpl_instance { uint8_t dio_intcurrent; uint8_t dio_send; /* for keeping track of which mode the timer is in */ uint8_t dio_counter; + /* my last registered DAO that I might be waiting for ACK on */ + uint8_t my_dao_seqno; + uint8_t my_dao_transmissions; + /* this is intended to keep track if this instance have a route downward */ + uint8_t has_downward_route; rpl_rank_t max_rankinc; rpl_rank_t min_hoprankinc; uint16_t lifetime_unit; /* lifetime in seconds = l_u * d_l */ @@ -233,6 +247,9 @@ struct rpl_instance { struct ctimer dao_lifetime_timer; struct ctimer unicast_dio_timer; rpl_parent_t *unicast_dio_target; +#if RPL_WITH_DAO_ACK + struct ctimer dao_retransmit_timer; +#endif /* RPL_WITH_DAO_ACK */ }; /*---------------------------------------------------------------------------*/ @@ -293,5 +310,13 @@ enum rpl_mode rpl_set_mode(enum rpl_mode mode); */ enum rpl_mode rpl_get_mode(void); + +/** + * Get the RPL's best guess on if we have downward route or not. + * + * \retval 1 if we have a downward route from RPL Root, 0 if not. + */ +int rpl_has_downward_route(void); + /*---------------------------------------------------------------------------*/ #endif /* RPL_H */ diff --git a/examples/er-rest-example/project-conf.h b/examples/er-rest-example/project-conf.h index 53662619a..adcb75ee1 100644 --- a/examples/er-rest-example/project-conf.h +++ b/examples/er-rest-example/project-conf.h @@ -60,6 +60,9 @@ #undef NETSTACK_CONF_RDC #define NETSTACK_CONF_RDC nullrdc_driver +#undef RPL_CONF_MAX_DAG_PER_INSTANCE +#define RPL_CONF_MAX_DAG_PER_INSTANCE 1 + /* Disabling TCP on CoAP nodes. */ #undef UIP_CONF_TCP #define UIP_CONF_TCP 0 @@ -93,6 +96,13 @@ #undef COAP_PROXY_OPTION_PROCESSING #define COAP_PROXY_OPTION_PROCESSING 0 +/* Turn of DAO ACK to make code smaller */ +#undef RPL_CONF_WITH_DAO_ACK +#define RPL_CONF_WITH_DAO_ACK 0 + +#undef RPL_CONF_OF +#define RPL_CONF_OF rpl_of0 + /* Enable client-side support for COAP observe */ #define COAP_OBSERVE_CLIENT 1 #endif /* __PROJECT_ERBIUM_CONF_H__ */ diff --git a/examples/ipv6/rpl-collect/Makefile b/examples/ipv6/rpl-collect/Makefile index ce20c79e2..e2a1021a0 100644 --- a/examples/ipv6/rpl-collect/Makefile +++ b/examples/ipv6/rpl-collect/Makefile @@ -3,6 +3,8 @@ APPS = powertrace collect-view CONTIKI_PROJECT = udp-sender udp-sink PROJECT_SOURCEFILES += collect-common.c +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + ifdef PERIOD CFLAGS=-DPERIOD=$(PERIOD) endif diff --git a/examples/ipv6/rpl-collect/project-conf.h b/examples/ipv6/rpl-collect/project-conf.h new file mode 100644 index 000000000..4b39f7de9 --- /dev/null +++ b/examples/ipv6/rpl-collect/project-conf.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#undef NBR_TABLE_CONF_MAX_NEIGHBORS +#undef UIP_CONF_MAX_ROUTES + +#ifdef TEST_MORE_ROUTES +/* configure number of neighbors and routes */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#define UIP_CONF_MAX_ROUTES 30 +#else +/* configure number of neighbors and routes */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#define UIP_CONF_MAX_ROUTES 10 +#endif /* TEST_MORE_ROUTES */ + +#undef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC nullrdc_driver +#undef NULLRDC_CONF_802154_AUTOACK +#define NULLRDC_CONF_802154_AUTOACK 1 + +/* Define as minutes */ +#define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 + +/* 10 minutes lifetime of routes */ +#define RPL_CONF_DEFAULT_LIFETIME 10 + +#define RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME 1 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/ipv6/rpl-udp/Makefile b/examples/ipv6/rpl-udp/Makefile index 9670d71e3..fbf9a589e 100644 --- a/examples/ipv6/rpl-udp/Makefile +++ b/examples/ipv6/rpl-udp/Makefile @@ -1,7 +1,8 @@ all: udp-client udp-server -APPS=servreg-hack CONTIKI=../../.. +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + ifdef WITH_COMPOWER APPS+=powertrace CFLAGS+= -DCONTIKIMAC_CONF_COMPOWER=1 -DWITH_COMPOWER=1 -DQUEUEBUF_CONF_NUM=4 diff --git a/examples/ipv6/rpl-udp/project-conf.h b/examples/ipv6/rpl-udp/project-conf.h new file mode 100644 index 000000000..4b39f7de9 --- /dev/null +++ b/examples/ipv6/rpl-udp/project-conf.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#undef NBR_TABLE_CONF_MAX_NEIGHBORS +#undef UIP_CONF_MAX_ROUTES + +#ifdef TEST_MORE_ROUTES +/* configure number of neighbors and routes */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#define UIP_CONF_MAX_ROUTES 30 +#else +/* configure number of neighbors and routes */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#define UIP_CONF_MAX_ROUTES 10 +#endif /* TEST_MORE_ROUTES */ + +#undef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC nullrdc_driver +#undef NULLRDC_CONF_802154_AUTOACK +#define NULLRDC_CONF_802154_AUTOACK 1 + +/* Define as minutes */ +#define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 + +/* 10 minutes lifetime of routes */ +#define RPL_CONF_DEFAULT_LIFETIME 10 + +#define RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME 1 + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/ipv6/rpl-udp/rpl-udp-scale-wismote.csc b/examples/ipv6/rpl-udp/rpl-udp-scale-wismote.csc new file mode 100644 index 000000000..3aea07ab0 --- /dev/null +++ b/examples/ipv6/rpl-udp/rpl-udp-scale-wismote.csc @@ -0,0 +1,721 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + RPL up and downstream scaleability test network using IPv6 and RPL + generated + 5000000 + + org.contikios.cooja.radiomediums.UDGM + 150.0 + 150.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.mspmote.WismoteMoteType + sky1 + WisMote Type #sky1 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.c + make SERVER_REPLY=1 clean udp-server.wismote TARGET=wismote DEFINES=TEST_MORE_ROUTES=1 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.wismote + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.MspButton + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspDefaultSerial + org.contikios.cooja.mspmote.interfaces.MspLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + + + org.contikios.cooja.mspmote.WismoteMoteType + sky2 + WisMote Type #sky2 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.c + make SERVER_REPLY=1 clean udp-client.wismote TARGET=wismote + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.wismote + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.MspButton + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspDefaultSerial + org.contikios.cooja.mspmote.interfaces.MspLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + + + + + org.contikios.cooja.interfaces.Position + 48.435974731198804 + -66.16503914182063 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 1 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + -65.3176930733124 + 17.4304162608286 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 2 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 127.9689727848476 + 91.71883780610729 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 3 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 154.92605604103275 + 40.97896551774433 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 4 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 47.34887596588397 + -30.341495695501195 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 5 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 47.13486576528276 + 32.944481932122315 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 6 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -11.42091423859419 + 17.879870626121914 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 7 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 118.92746659954325 + 57.05973076244069 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 8 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 56.66768196114595 + 74.35652008990945 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 9 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 16.45706316609417 + 23.9075414163248 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 10 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -13.423161364506493 + -38.483037144768275 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 11 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -9.034961217472201 + 44.411389162165406 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 12 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 35.60049910164592 + 87.95154356223047 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 13 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 66.93880603404335 + -42.39683727590697 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 14 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 94.81678343873172 + 26.921376811426246 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 15 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -49.449656689283934 + 57.924813144367945 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 16 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -34.02467970185502 + -24.313824905298304 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 17 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -28.750467760427494 + 48.01822457713635 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 18 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 124.95513738974614 + 20.140247172447996 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 19 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 14.85247487703553 + -34.478542892943686 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 20 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 154.43072661267115 + -3.279765376986134 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 21 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 99.90960713878738 + -21.76043658444847 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 22 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 88.4612185198951 + -49.763990463932714 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 23 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 24.745110502623138 + -1.7100594420374744 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 24 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 94.06332458995635 + -2.4635182908128352 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 25 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -4.639784599615941 + -10.849236218849724 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 26 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 2.4901685804620115 + -60.89843789583528 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 27 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 100.55144245441083 + 97.41861446767646 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 28 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -12.355761328741393 + 82.72616691655692 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 29 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 57.79962925723111 + 0.6828700499064966 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 30 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 76.5550413097159 + 77.33875258624342 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 31 + + sky2 + + + + org.contikios.cooja.plugins.SimControl + 289 + 4 + 184 + 31 + 41 + + + org.contikios.cooja.plugins.Visualizer + + true + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.AttributeVisualizerSkin + 2.349818846983307 0.0 0.0 2.349818846983307 187.19773526533345 190.95275613586946 + + 659 + 2 + 622 + 296 + 11 + + + org.contikios.cooja.plugins.LogListener + + ID:22.*DAO + + + + 937 + 3 + 442 + 20 + 297 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 600 + 5 + 700 + 946 + 6 + + + org.contikios.cooja.plugins.MoteInterfaceViewer + 3 + + Position + 0,0 + + 350 + 6 + 300 + 976 + 36 + + + diff --git a/examples/ipv6/rpl-udp/rpl-udp-scale.csc b/examples/ipv6/rpl-udp/rpl-udp-scale.csc new file mode 100644 index 000000000..292e442c1 --- /dev/null +++ b/examples/ipv6/rpl-udp/rpl-udp-scale.csc @@ -0,0 +1,729 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + RPL up and downstream scaleability test network using IPv6 and RPL + generated + 5000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.mspmote.SkyMoteType + sky1 + Sky Mote Type #sky1 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.c + make SERVER_REPLY=1 clean udp-server.sky TARGET=sky DEFINES=TEST_MORE_ROUTES=1 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + org.contikios.cooja.mspmote.SkyMoteType + sky2 + Sky Mote Type #sky2 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.c + make SERVER_REPLY=1 clean udp-client.sky TARGET=sky + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + + + org.contikios.cooja.interfaces.Position + 48.435974731198804 + -66.16503914182063 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 1 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + -39.78380986481406 + -48.10655064098382 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 2 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 127.9689727848476 + 91.71883780610729 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 3 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 154.92605604103275 + 40.97896551774433 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 4 + + + org.contikios.cooja.mspmote.interfaces.MspSerial + r~; + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 47.34887596588397 + -30.341495695501195 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 5 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 47.13486576528276 + 32.944481932122315 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 6 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -11.42091423859419 + 17.879870626121914 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 7 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 118.92746659954325 + 57.05973076244069 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 8 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 53.68872892015448 + 59.887319605093715 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 9 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 16.45706316609417 + 23.9075414163248 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 10 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -13.423161364506493 + -38.483037144768275 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 11 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -9.034961217472201 + 44.411389162165406 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 12 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -39.298891643282545 + -3.9704359883635574 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 13 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 66.93880603404335 + -42.39683727590697 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 14 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 94.81678343873172 + 26.921376811426246 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 15 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -43.06618588715935 + 30.68867105530305 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 16 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -34.02467970185502 + -24.313824905298304 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 17 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -28.750467760427494 + 48.01822457713635 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 18 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 124.95513738974614 + 20.140247172447996 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 19 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 15.703604317318808 + -47.6710492173345 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 20 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 154.43072661267115 + -3.279765376986134 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 21 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 121.18784314586934 + -24.313824905298304 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 22 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 88.4612185198951 + -49.763990463932714 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 23 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 24.745110502623138 + -1.7100594420374744 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 24 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 94.06332458995635 + -2.4635182908128352 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 25 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -4.639784599615941 + -9.998106778566445 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 26 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 2.4901685804620115 + -60.89843789583528 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 27 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 103.10483077526068 + 96.99304974753483 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 28 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 8.922474678340558 + 59.320107308766765 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 29 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 58.650758697514384 + 2.8106936506146916 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 30 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 90.59867707439 + 67.97632874312737 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 31 + + sky2 + + + + org.contikios.cooja.plugins.SimControl + 289 + 1 + 184 + 31 + 41 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.AttributeVisualizerSkin + 2.349818846983307 0.0 0.0 2.349818846983307 187.19773526533345 190.95275613586946 + + 659 + 3 + 523 + 296 + 11 + + + org.contikios.cooja.plugins.LogListener + + + + + + 937 + 4 + 349 + 21 + 464 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 600 + 0 + 700 + 946 + 6 + + + org.contikios.cooja.plugins.MoteInterfaceViewer + 3 + + Serial port + 0,0 + + 350 + 2 + 300 + 976 + 36 + + diff --git a/examples/ipv6/rpl-udp/rpl-udp.csc b/examples/ipv6/rpl-udp/rpl-udp.csc index cf7c049f1..3aa9b270e 100644 --- a/examples/ipv6/rpl-udp/rpl-udp.csc +++ b/examples/ipv6/rpl-udp/rpl-udp.csc @@ -1,12 +1,13 @@ - [CONTIKI_DIR]/tools/cooja/apps/mrm - [CONTIKI_DIR]/tools/cooja/apps/mspsim - [CONTIKI_DIR]/tools/cooja/apps/avrora - [CONTIKI_DIR]/tools/cooja/apps/mobility + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker Data collection network using IPv6 and RPL - 0 generated 5000000 @@ -24,7 +25,7 @@ sky1 Sky Mote Type #sky1 [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.c - make udp-server.sky TARGET=sky + make clean udp-server.sky TARGET=sky DEFINES=TEST_MORE_ROUTES=1 [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.sky org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.RimeAddress @@ -47,7 +48,7 @@ sky2 Sky Mote Type #sky2 [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.c - make udp-client.sky TARGET=sky + make clean udp-client.sky TARGET=sky [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.sky org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.RimeAddress @@ -73,6 +74,10 @@ -66.16503914182063 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 1 @@ -87,6 +92,10 @@ 98.28771308774003 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 2 @@ -101,6 +110,10 @@ 91.71883780610729 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 3 @@ -115,6 +128,10 @@ 92.47229665488265 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 4 @@ -129,6 +146,10 @@ -30.341495695501195 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 5 @@ -143,6 +164,10 @@ 32.944481932122315 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 6 @@ -157,6 +182,10 @@ 17.879870626121914 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 7 @@ -171,6 +200,10 @@ 57.05973076244069 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 8 @@ -185,6 +218,10 @@ 59.887319605093715 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 9 @@ -199,6 +236,10 @@ 23.9075414163248 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 10 @@ -213,6 +254,10 @@ 75.14274313304935 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 11 @@ -227,6 +272,10 @@ 85.6911670159044 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 12 @@ -241,6 +290,10 @@ -3.9704359883635574 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 13 @@ -255,6 +308,10 @@ -42.39683727590697 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 14 @@ -269,6 +326,10 @@ 26.921376811426246 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 15 @@ -283,6 +344,10 @@ 30.68867105530305 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 16 @@ -297,6 +362,10 @@ -24.313824905298304 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 17 @@ -311,6 +380,10 @@ 48.01822457713635 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 18 @@ -325,6 +398,10 @@ 20.140247172447996 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 19 @@ -339,6 +416,10 @@ -47.6710492173345 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 20 @@ -353,6 +434,10 @@ 92.47229665488265 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 21 @@ -367,6 +452,10 @@ -24.313824905298304 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 22 @@ -381,6 +470,10 @@ -44.657213822233054 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 23 @@ -395,6 +488,10 @@ -1.7100594420374744 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 24 @@ -409,6 +506,10 @@ -2.4635182908128352 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 25 @@ -423,6 +524,10 @@ -9.998106778566445 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 26 @@ -437,6 +542,10 @@ -50.684884612435944 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 27 @@ -451,6 +560,10 @@ 96.99304974753483 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 28 @@ -465,6 +578,10 @@ 59.320107308766765 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 29 @@ -479,6 +596,10 @@ 2.8106936506146916 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 30 @@ -493,6 +614,10 @@ 67.97632874312737 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 31 @@ -503,10 +628,10 @@ org.contikios.cooja.plugins.SimControl 259 - 1 + 3 184 - 0 - 0 + 3 + 15 org.contikios.cooja.plugins.Visualizer @@ -517,21 +642,23 @@ 2.349818846983307 0.0 0.0 2.349818846983307 150.19773526533348 176.95275613586946 520 - 3 + 2 523 - 269 - 14 + 14 + 210 org.contikios.cooja.plugins.LogListener + + 937 0 213 - 21 - 464 + 265 + 16 org.contikios.cooja.plugins.ScriptRunner @@ -574,11 +701,11 @@ while(1) { } true - 600 - 2 - 700 - 665 - 6 + 651 + 1 + 550 + 547 + 181 diff --git a/examples/ipv6/rpl-udp/udp-client.c b/examples/ipv6/rpl-udp/udp-client.c index 279703880..e5339fc3d 100644 --- a/examples/ipv6/rpl-udp/udp-client.c +++ b/examples/ipv6/rpl-udp/udp-client.c @@ -40,12 +40,17 @@ #include #include +/* Only for TMOTE Sky? */ +#include "dev/serial-line.h" +#include "dev/uart1.h" +#include "net/ipv6/uip-ds6-route.h" + #define UDP_CLIENT_PORT 8765 #define UDP_SERVER_PORT 5678 #define UDP_EXAMPLE_ID 190 -#define DEBUG DEBUG_PRINT +#define DEBUG DEBUG_FULL #include "net/ip/uip-debug.h" #ifndef PERIOD @@ -64,6 +69,9 @@ static uip_ipaddr_t server_ipaddr; PROCESS(udp_client_process, "UDP client process"); AUTOSTART_PROCESSES(&udp_client_process); /*---------------------------------------------------------------------------*/ +static int seq_id; +static int reply; + static void tcpip_handler(void) { @@ -72,16 +80,32 @@ tcpip_handler(void) if(uip_newdata()) { str = uip_appdata; str[uip_datalen()] = '\0'; - printf("DATA recv '%s'\n", str); + reply++; + printf("DATA recv '%s' (s:%d, r:%d)\n", str, seq_id, reply); } } /*---------------------------------------------------------------------------*/ static void send_packet(void *ptr) { - static int seq_id; char buf[MAX_PAYLOAD_LEN]; +#ifdef SERVER_REPLY + uint8_t num_used = 0; + uip_ds6_nbr_t *nbr; + + nbr = nbr_table_head(ds6_neighbors); + while(nbr != NULL) { + nbr = nbr_table_next(ds6_neighbors, nbr); + num_used++; + } + + if(seq_id > 0) { + ANNOTATE("#A r=%d/%d,color=%s,n=%d %d\n", reply, seq_id, + reply == seq_id ? "GREEN" : "RED", uip_ds6_route_num_routes(), num_used); + } +#endif /* SERVER_REPLY */ + seq_id++; PRINTF("DATA send to %d 'Hello %d'\n", server_ipaddr.u8[sizeof(server_ipaddr.u8) - 1], seq_id); @@ -156,8 +180,9 @@ PROCESS_THREAD(udp_client_process, ev, data) PROCESS_PAUSE(); set_global_address(); - - PRINTF("UDP client process started\n"); + + PRINTF("UDP client process started nbr:%d routes:%d\n", + NBR_TABLE_CONF_MAX_NEIGHBORS, UIP_CONF_MAX_ROUTES); print_local_addresses(); @@ -174,6 +199,11 @@ PROCESS_THREAD(udp_client_process, ev, data) PRINTF(" local/remote port %u/%u\n", UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport)); + /* initialize serial line */ + uart1_set_input(serial_line_input_byte); + serial_line_init(); + + #if WITH_COMPOWER powertrace_sniff(POWERTRACE_ON); #endif @@ -184,7 +214,41 @@ PROCESS_THREAD(udp_client_process, ev, data) if(ev == tcpip_event) { tcpip_handler(); } - + + if(ev == serial_line_event_message && data != NULL) { + char *str; + str = data; + if(str[0] == 'r') { + uip_ds6_route_t *r; + uip_ipaddr_t *nexthop; + uip_ds6_defrt_t *defrt; + uip_ipaddr_t *ipaddr; + defrt = NULL; + if((ipaddr = uip_ds6_defrt_choose()) != NULL) { + defrt = uip_ds6_defrt_lookup(ipaddr); + } + if(defrt != NULL) { + PRINTF("DefRT: :: -> %02d", defrt->ipaddr.u8[15]); + PRINTF(" lt:%lu inf:%d\n", stimer_remaining(&defrt->lifetime), + defrt->isinfinite); + } else { + PRINTF("DefRT: :: -> NULL\n"); + } + + for(r = uip_ds6_route_head(); + r != NULL; + r = uip_ds6_route_next(r)) { + nexthop = uip_ds6_route_nexthop(r); + PRINTF("Route: %02d -> %02d", r->ipaddr.u8[15], nexthop->u8[15]); + /* PRINT6ADDR(&r->ipaddr); */ + /* PRINTF(" -> "); */ + /* PRINT6ADDR(nexthop); */ + PRINTF(" lt:%lu\n", r->state.lifetime); + + } + } + } + if(etimer_expired(&periodic)) { etimer_reset(&periodic); ctimer_set(&backoff_timer, SEND_TIME, send_packet, NULL); diff --git a/examples/ipv6/rpl-udp/udp-server.c b/examples/ipv6/rpl-udp/udp-server.c index 17c1b1fb8..ce87d3b8f 100644 --- a/examples/ipv6/rpl-udp/udp-server.c +++ b/examples/ipv6/rpl-udp/udp-server.c @@ -107,7 +107,8 @@ PROCESS_THREAD(udp_server_process, ev, data) SENSORS_ACTIVATE(button_sensor); - PRINTF("UDP server started\n"); + PRINTF("UDP server started. nbr:%d routes:%d\n", + NBR_TABLE_CONF_MAX_NEIGHBORS, UIP_CONF_MAX_ROUTES); #if UIP_CONF_ROUTER /* The choice of server address determines its 6LoPAN header compression. diff --git a/platform/cc2530dk/viztool.c b/platform/cc2530dk/viztool.c index e6b2fbed3..1901e9f74 100644 --- a/platform/cc2530dk/viztool.c +++ b/platform/cc2530dk/viztool.c @@ -127,8 +127,8 @@ process_request() CC_NON_BANKED if(rt != NULL) { entry_size = sizeof(i) + sizeof(rt->ipaddr) + sizeof(rt->length) - + sizeof(rt->state.lifetime) - + sizeof(rt->state.learned_from); + + sizeof(rt->state.lifetime); + /* + sizeof(rt->state.learned_from); */ memcpy(buf + len, &i, sizeof(i)); len += sizeof(i); @@ -147,11 +147,11 @@ process_request() CC_NON_BANKED len += sizeof(flip); PRINTF(" - %08lx", rt->state.lifetime); - memcpy(buf + len, &rt->state.learned_from, - sizeof(rt->state.learned_from)); - len += sizeof(rt->state.learned_from); + /* memcpy(buf + len, &rt->state.learned_from, */ + /* sizeof(rt->state.learned_from)); */ + /* len += sizeof(rt->state.learned_from); */ - PRINTF(" - %02x [%u]\n", rt->state.learned_from, entry_size); + PRINTF(" - [%u]\n", entry_size); count++; left -= entry_size; diff --git a/platform/micaz/contiki-conf.h b/platform/micaz/contiki-conf.h index 16e74567a..04aaccf6b 100644 --- a/platform/micaz/contiki-conf.h +++ b/platform/micaz/contiki-conf.h @@ -125,10 +125,11 @@ #define UIP_CONF_ROUTER 0 /* configure number of neighbors and routes */ -#define NBR_TABLE_CONF_MAX_NEIGHBORS 5 -#define UIP_CONF_MAX_ROUTES 5 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 5 +#define UIP_CONF_MAX_ROUTES 5 -#define RPL_CONF_MAX_PARENTS 4 +#define RPL_CONF_MAX_PARENTS 4 +#define RPL_CONF_MAX_DAG_PER_INSTANCE 1 #define UIP_CONF_ND6_SEND_RA 0 #define UIP_CONF_ND6_REACHABLE_TIME 600000 @@ -140,12 +141,12 @@ #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 #define UIP_CONF_IP_FORWARD 0 -#define UIP_CONF_BUFFER_SIZE 240 +#define UIP_CONF_BUFFER_SIZE 200 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 -#define SICSLOWPAN_CONF_FRAGMENT_BUFFERS 4 +#define SICSLOWPAN_CONF_FRAGMENT_BUFFERS 3 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 diff --git a/regression-tests/12-rpl/04-rpl-large-network.csc b/regression-tests/12-rpl/04-rpl-large-network.csc index 8b3ca0d8a..145cad14c 100644 --- a/regression-tests/12-rpl/04-rpl-large-network.csc +++ b/regression-tests/12-rpl/04-rpl-large-network.csc @@ -7057,5 +7057,4 @@ while(true) { 603 43 - - + \ No newline at end of file diff --git a/regression-tests/21-large-rpl/code/node/client.c b/regression-tests/21-large-rpl/code/node/client.c index 386f18529..1e82e2df0 100644 --- a/regression-tests/21-large-rpl/code/node/client.c +++ b/regression-tests/21-large-rpl/code/node/client.c @@ -10,6 +10,7 @@ static struct http_socket s; static int bytes_received = 0; static int restarts; static struct ctimer reconnect_timer; +static int connect = 0; static void callback(struct http_socket *s, void *ptr, http_socket_event_t e, @@ -22,9 +23,9 @@ AUTOSTART_PROCESSES(&http_example_process); static void reconnect(void *dummy) { + printf("#A color=orange\n"); rpl_set_mode(RPL_MODE_MESH); - http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, - callback, NULL); + connect = 1; } /*---------------------------------------------------------------------------*/ static void @@ -33,6 +34,8 @@ restart(void) int scale; restarts++; printf("restart %d\n", restarts); + rpl_set_mode(RPL_MODE_FEATHER); + printf("#A color=red\n"); scale = restarts; if(scale > 5) { @@ -62,6 +65,7 @@ callback(struct http_socket *s, void *ptr, if(bytes_received > 0) { printf("HTTP socket closed, %d bytes received\n", bytes_received); leds_off(LEDS_RED); + printf("#A color=blue\n"); rpl_set_mode(RPL_MODE_FEATHER); } else { restart(); @@ -72,6 +76,7 @@ callback(struct http_socket *s, void *ptr, } } /*---------------------------------------------------------------------------*/ + PROCESS_THREAD(http_example_process, ev, data) { static struct etimer et; @@ -88,14 +93,26 @@ PROCESS_THREAD(http_example_process, ev, data) PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); http_socket_init(&s); - http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, - callback, NULL); + connect = 1; leds_on(LEDS_RED); restarts = 0; - etimer_set(&et, CLOCK_SECOND); + etimer_set(&et, CLOCK_SECOND * 5); while(1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); + if(connect && rpl_has_downward_route()) { + printf("#A color=green\n"); + http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, + callback, NULL); + connect = 0; + } else if(connect) { + connect++; + /* If connect have been "tried" 5 timer we quit trying now... */ + if(connect > 5) { + restart(); + connect = 0; + } + } } PROCESS_END(); diff --git a/regression-tests/21-large-rpl/code/router/project-conf.h b/regression-tests/21-large-rpl/code/router/project-conf.h index eb0b0b1a7..857ab6929 100644 --- a/regression-tests/21-large-rpl/code/router/project-conf.h +++ b/regression-tests/21-large-rpl/code/router/project-conf.h @@ -7,5 +7,5 @@ #undef NBR_TABLE_CONF_MAX_NEIGHBORS #define NBR_TABLE_CONF_MAX_NEIGHBORS 8 -/*#define RPL_CONF_DEFAULT_LIFETIME_UNIT 10 - #define RPL_CONF_DEFAULT_LIFETIME 10*/ +/* #define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 */ +/* #define RPL_CONF_DEFAULT_LIFETIME 10 */ diff --git a/regression-tests/21-large-rpl/code/router/router.c b/regression-tests/21-large-rpl/code/router/router.c index 844afdc1c..65882c36c 100644 --- a/regression-tests/21-large-rpl/code/router/router.c +++ b/regression-tests/21-large-rpl/code/router/router.c @@ -3,13 +3,23 @@ #include "ip64.h" #include "net/netstack.h" #include "net/rpl/rpl-dag-root.h" - +#include "net/rpl/rpl.h" +#include "net/ipv6/uip-ds6-route.h" +#include /*---------------------------------------------------------------------------*/ PROCESS(router_node_process, "Router node"); AUTOSTART_PROCESSES(&router_node_process); /*---------------------------------------------------------------------------*/ +uip_lladdr_t * uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route); + + PROCESS_THREAD(router_node_process, ev, data) { + uip_ipaddr_t *nexthop = NULL; + uip_ds6_defrt_t *defrt; + uip_ipaddr_t *ipaddr; + uip_ds6_route_t *r; + static struct etimer et; PROCESS_BEGIN(); /* Set us up as a RPL root node. */ @@ -18,9 +28,41 @@ PROCESS_THREAD(router_node_process, ev, data) /* Initialize the IP64 module so we'll start translating packets */ ip64_init(); + /* etimer_set(&et, CLOCK_SECOND * 60); */ + /* PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); */ + /* ... and do nothing more. */ while(1) { - PROCESS_WAIT_EVENT(); + etimer_set(&et, CLOCK_SECOND * 20); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + defrt = NULL; + if((ipaddr = uip_ds6_defrt_choose()) != NULL) { + defrt = uip_ds6_defrt_lookup(ipaddr); + } + if(defrt != NULL) { + printf("DefRT: :: -> %02d", defrt->ipaddr.u8[15]); + printf(" lt:%lu inf:%d\n", stimer_remaining(&defrt->lifetime), + defrt->isinfinite); + } else { + printf("DefRT: :: -> NULL\n"); + } + + if(uip_ds6_route_head() != NULL) { + printf("found head\n"); + for(r = uip_ds6_route_head(); + r != NULL; + r = uip_ds6_route_next(r)) { + nexthop = uip_ds6_route_nexthop(r); + if(nexthop != NULL) { + printf("Route: %02d -> %02d", r->ipaddr.u8[15], nexthop->u8[15]); + } else { + //printf("Route: %p %02d -> ? nbr-routes:%p", r, r->ipaddr.u8[15], + //r->neighbor_routes); + } + printf(" lt:%lu\n", r->state.lifetime); + } + } } PROCESS_END();