From 946be772484697897af2ec5266f5d3cd1a2473eb Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Wed, 19 Aug 2015 15:50:20 +0200 Subject: [PATCH 01/30] Added support for end-to-end DAO ACK for Contiki RPL. This is a fix for Contiki RPL so that it fully supports DAO ACK in an end-to-end fashion. When DAO is sent it will be forwarded upwards as before. DAO ACK will be forwarded downwards until it reach the node that initiated the DAO ACK and unlike before it is not a single-hop DAO ACK but it is fully reaching the RPL ROOT before any DAO ACK is sent back. DAO ACK also now fully support different status messages (success / fail). --- core/net/ipv6/uip-ds6-route.h | 37 ++++- core/net/rpl/rpl-conf.h | 10 ++ core/net/rpl/rpl-dag.c | 2 +- core/net/rpl/rpl-icmp6.c | 256 +++++++++++++++++++++++++++++++--- core/net/rpl/rpl-mrhof.c | 16 +++ core/net/rpl/rpl-of0.c | 1 + core/net/rpl/rpl-private.h | 12 +- core/net/rpl/rpl.c | 2 +- core/net/rpl/rpl.h | 7 + 9 files changed, 316 insertions(+), 27 deletions(-) diff --git a/core/net/ipv6/uip-ds6-route.h b/core/net/ipv6/uip-ds6-route.h index 342bfeffa..8df18796b 100644 --- a/core/net/ipv6/uip-ds6-route.h +++ b/core/net/ipv6/uip-ds6-route.h @@ -97,11 +97,42 @@ 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_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(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 */ diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index 5511b8289..2ff9fbf91 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -235,6 +235,16 @@ #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 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..04c64a50d 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -1028,7 +1028,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_set_default_route(instance, from); if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { - rpl_schedule_dao(instance); + rpl_schedule_dao_immediately(instance); } else { PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); } diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 14de349fe..e1ac899ba 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -76,6 +76,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 *); @@ -85,6 +88,7 @@ void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *); void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); #endif +/* TODO: should these variables be a part of the instance? */ static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; extern rpl_of_t RPL_OF; @@ -99,6 +103,37 @@ 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) { @@ -723,28 +758,37 @@ 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); + /* indicate that we accepted the no-path DAO */ + dao_ack_output(instance, &dao_sender_addr, sequence, + RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); } } goto discard; @@ -781,28 +825,64 @@ dao_input(void) 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, + RPL_DAO_ACK_UNABLE_TO_ACCEPT); + } goto discard; } rep->state.lifetime = RPL_LIFETIME(instance, lifetime); - rep->state.learned_from = learned_from; - rep->state.nopath_received = 0; + /* rep->state.learned_from = learned_from; */ + /* rep->state.nopath_received = 0; */ #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. */ + 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); + + /* Ack sent immediately after forwarding (otherwise the packets is + corrupted. */ + if(should_ack) { + PRINTF("RPL: sending DAO ACK\n"); + dao_ack_output(instance, &dao_sender_addr, sequence, + RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); } } @@ -810,23 +890,95 @@ 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 - what now ??? */ + if(instance->lifetime_unit == 0xffff && instance->default_lifetime == 0xff) { + /* RPL is using infinite lifetime for routes. This probably + means that the root is 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 about the timeout for taking decision on punishment */ + instance->of->dao_ack_callback(parent, RPL_DAO_ACK_TIMEOUT); + } + + rpl_local_repair(instance); + /* give up this and hope to find another parent */ + 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, + 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) { /* Destination Advertisement Object */ uip_ipaddr_t prefix; + rpl_instance_t *instance; if(get_global_addr(&prefix) == 0) { PRINTF("RPL: No global address set for this node - suppressing DAO\n"); return; } + if(parent == NULL || parent->dag == NULL || parent->dag->instance == NULL) { + return; + } + instance = parent->dag->instance; + /* Sending a DAO with own prefix as target */ dao_output_target(parent, &prefix, lifetime); + /* keep track of my own sending of DAO for handling ack and loss of ack */ + instance->my_dao_seqno = dao_sequence; + +#if RPL_WITH_DAO_ACK + instance->my_dao_transmissions = 1; + ctimer_set(&instance->dao_retransmit_timer, RPL_DAO_RETRANSMISSION_TIMEOUT, + handle_dao_retransmission, parent); +#endif /* RPL_WITH_DAO_ACK */ } /*---------------------------------------------------------------------------*/ 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 +1019,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 +1026,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); @@ -918,41 +1068,105 @@ 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; 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) { + return; + } + + parent = rpl_find_parent(instance->current_dag, &UIP_IP_BUF->srcipaddr); + if(parent == NULL) { + /* not a known instance - did we switch?? */ + // PRINTF("RPL: Received a DAO ACK from a not joined instance: %d", + // instance_id); + return; + } + + PRINTF("RPL: Received a DAO ACK with sequence number %d (%d) and status %d from ", + sequence, instance->my_dao_seqno, status); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); #endif /* DEBUG */ + + if(sequence == instance->my_dao_seqno) { + PRINTF("RPL: DAO ACK for me!\n"); + + /* 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(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); + } + } else { + /* this DAO 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("No next hop to fwd DAO ACK to\n"); + } else { + PRINTF("Fwd DAO ACK\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("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); 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..acf2b1d54 100644 --- a/core/net/rpl/rpl-mrhof.c +++ b/core/net/rpl/rpl-mrhof.c @@ -54,6 +54,7 @@ static void reset(rpl_dag_t *); static void neighbor_link_callback(rpl_parent_t *, int, int); +static void dao_ack_callback(rpl_parent_t *, int); 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 +63,7 @@ static void update_metric_container(rpl_instance_t *); rpl_of_t rpl_mrhof = { reset, neighbor_link_callback, + dao_ack_callback, best_parent, best_dag, calculate_rank, @@ -117,6 +119,20 @@ reset(rpl_dag_t *dag) PRINTF("RPL: Reset MRHOF\n"); } +static void +dao_ack_callback(rpl_parent_t *p, int status) +{ + /* here we need to handle failed DAO's and other stuff */ + PRINTF("RPL: MRHOF - DAO ACK received with status: %d", 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); + } +} + static void neighbor_link_callback(rpl_parent_t *p, int status, int numtx) { diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index ca73169fc..ed76bac4b 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -55,6 +55,7 @@ static void update_metric_container(rpl_instance_t *); rpl_of_t rpl_of0 = { reset, NULL, + NULL, best_parent, best_dag, calculate_rank, diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index e1d95697b..5a7a9be94 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -90,6 +90,13 @@ #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_TIMEOUT -1 + /*---------------------------------------------------------------------------*/ /* RPL IPv6 extension header option. */ #define RPL_HDR_OPT_LEN 4 @@ -117,6 +124,9 @@ #define RPL_NOPATH_REMOVAL_DELAY 60 #endif /* RPL_CONF_NOPATH_REMOVAL_DELAY */ +#define RPL_DAO_MAX_RETRANSMISSIONS 5 +#define RPL_DAO_RETRANSMISSION_TIMEOUT (5 * CLOCK_SECOND) + /* Special value indicating immediate removal. */ #define RPL_ZERO_LIFETIME 0 @@ -268,7 +278,7 @@ 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); /* RPL logic functions. */ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 7e7947e34..da5822757 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -238,7 +238,7 @@ 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; + /* rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL; */ PRINTF("RPL: Added a route to "); PRINT6ADDR(prefix); diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 54b63c875..b7d7757c2 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -185,6 +185,7 @@ typedef struct rpl_instance rpl_instance_t; struct rpl_of { void (*reset)(struct rpl_dag *); void (*neighbor_link_callback)(rpl_parent_t *, int, int); + void (*dao_ack_callback)(rpl_parent_t *, int status); 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 +217,9 @@ 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; rpl_rank_t max_rankinc; rpl_rank_t min_hoprankinc; uint16_t lifetime_unit; /* lifetime in seconds = l_u * d_l */ @@ -233,6 +237,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 */ }; /*---------------------------------------------------------------------------*/ From 513393db54f0e393569d7fead52727bfa9513065 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 20 Aug 2015 16:56:50 +0200 Subject: [PATCH 02/30] added return value so that caller know if a nbr was removed or not --- core/net/ipv6/uip-ds6-nbr.c | 6 +++--- core/net/ipv6/uip-ds6-nbr.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index b793ab9f0..5905993a5 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -115,7 +115,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 +123,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..b0dd84d4a 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -88,7 +88,7 @@ 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); +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); From d181bd9e6ff8b5468522c0370177ee895fecf4f2 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 20 Aug 2015 17:00:47 +0200 Subject: [PATCH 03/30] added config for enabling/disabling removal of oldest route and added support function for checking if lladdress is used as nexthop --- core/net/ipv6/uip-ds6-route.c | 17 ++++++++++++++--- core/net/ipv6/uip-ds6-route.h | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 3f4ac81e7..3113986a1 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -207,6 +207,12 @@ uip_ds6_route_next(uip_ds6_route_t *r) } /*---------------------------------------------------------------------------*/ int +uip_ds6_route_is_nexthop(const uip_lladdr_t *lladdr) +{ + return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL; +} +/*---------------------------------------------------------------------------*/ +int uip_ds6_route_num_routes(void) { return num_routes; @@ -307,11 +313,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"); diff --git a/core/net/ipv6/uip-ds6-route.h b/core/net/ipv6/uip-ds6-route.h index 8df18796b..3324a8e08 100644 --- a/core/net/ipv6/uip-ds6-route.h +++ b/core/net/ipv6/uip-ds6-route.h @@ -197,7 +197,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_lladdr_t *lladdr); /** @} */ #endif /* UIP_DS6_ROUTE_H */ From 3fd8c4db2da52040f4a26aa398fbe41609e8f681 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 20 Aug 2015 17:09:32 +0200 Subject: [PATCH 04/30] added nbr policy for Contiki RPL that avoids thrashing the nbr table with new entries all the time --- core/net/rpl/rpl-conf.h | 12 ++ core/net/rpl/rpl-dag.c | 34 ++++- core/net/rpl/rpl-icmp6.c | 132 +++++++++--------- core/net/rpl/rpl-nbr-policy.c | 244 ++++++++++++++++++++++++++++++++++ core/net/rpl/rpl-private.h | 28 ++++ core/net/rpl/rpl.c | 1 - 6 files changed, 383 insertions(+), 68 deletions(-) create mode 100644 core/net/rpl/rpl-nbr-policy.c diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index 2ff9fbf91..831765974 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -245,6 +245,18 @@ #define RPL_WITH_DAO_ACK 1 #endif /* RPL_CONF_WITH_DAO_ACK */ +/* + * 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 04c64a50d..79f83a84e 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -1174,6 +1174,8 @@ rpl_local_repair(rpl_instance_t *instance) } 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 +1252,23 @@ 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) +{ + /* check if it is ok to add this nbr based on this DIO */ + if(RPL_NBR_POLICY.check_add_from_dio(from, dio)) { + /* add this to the neighbor cache if not already there */ + if(rpl_icmp6_update_nbr_table(from) == NULL) { + PRINTF("RPL: Out of memory, dropping DIO from "); + PRINT6ADDR(from); + PRINTF("\n"); + return 0; + } + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { @@ -1303,7 +1322,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 +1338,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 +1390,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 e1ac899ba..b0ab53de4 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -88,7 +88,6 @@ void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *); void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); #endif -/* TODO: should these variables be a part of the instance? */ static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; extern rpl_of_t RPL_OF; @@ -182,6 +181,32 @@ 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) +{ + uip_ds6_nbr_t *nbr; + + if((nbr = uip_ds6_nbr_lookup(from)) == NULL) { + if((nbr = uip_ds6_nbr_add(from, (uip_lladdr_t *) + packetbuf_addr(PACKETBUF_ADDR_SENDER), + 0, NBR_REACHABLE)) != NULL) { + 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 */ + stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); +#endif /* UIP_ND6_SEND_NA */ + } + return nbr; + } +/*---------------------------------------------------------------------------*/ static void dis_input(void) { @@ -205,8 +230,20 @@ 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_NBR_POLICY.check_add_from_dis(&UIP_IP_BUF->srcipaddr)) { + /* Add this to the neighbor cache if not already there */ + if(rpl_icmp6_update_nbr_table(&UIP_IP_BUF->srcipaddr) == NULL) { + PRINTF("RPL: Out of Memory, not sending unicast DIO, DIS from "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + return; + } + PRINTF("RPL: Unicast DIS, reply to sender\n"); + dio_output(instance, &UIP_IP_BUF->srcipaddr); + } } } } @@ -253,7 +290,6 @@ dio_input(void) int i; int len; uip_ipaddr_t from; - uip_ds6_nbr_t *nbr; memset(&dio, 0, sizeof(dio)); @@ -274,32 +310,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. */ @@ -796,29 +806,19 @@ dao_input(void) 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; - } - } else { - PRINTF("RPL: Neighbor already in neighbor cache\n"); + /* Check if we should add another neighbor based on DAO. */ + if(!RPL_NBR_POLICY.check_add_from_dao(&dao_sender_addr)) { + /* Do not add the neighbor. */ + return; + } + /* Update and add neighbor - if no room - fail. */ + if((nbr = rpl_icmp6_update_nbr_table(&dao_sender_addr)) == NULL) { + 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; } rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr); @@ -834,9 +834,8 @@ dao_input(void) goto discard; } + /* State is all zeroes, set lifetime but no need for other initialization. */ rep->state.lifetime = RPL_LIFETIME(instance, lifetime); - /* rep->state.learned_from = learned_from; */ - /* rep->state.nopath_received = 0; */ #if RPL_CONF_MULTICAST fwd_dao: @@ -877,8 +876,6 @@ fwd_dao: ICMP6_RPL, RPL_CODE_DAO, buffer_length); } - /* Ack sent immediately after forwarding (otherwise the packets is - corrupted. */ if(should_ack) { PRINTF("RPL: sending DAO ACK\n"); dao_ack_output(instance, &dao_sender_addr, sequence, @@ -897,30 +894,33 @@ handle_dao_retransmission(void *ptr) rpl_parent_t *parent; uip_ipaddr_t prefix; rpl_instance_t *instance; - parent = ptr; + 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 - what now ??? */ + /* No more retransmissions - give up. */ if(instance->lifetime_unit == 0xffff && instance->default_lifetime == 0xff) { - /* RPL is using infinite lifetime for routes. This probably - means that the root is 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. */ + /* + * 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 about the timeout for taking decision on punishment */ + /* 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); - /* give up this and hope to find another parent */ return; } @@ -1102,7 +1102,7 @@ dao_ack_input(void) #endif /* DEBUG */ if(sequence == instance->my_dao_seqno) { - PRINTF("RPL: DAO ACK for me!\n"); + PRINTF("RPL: DAO %s for me!\n", status < 128 ? "ACK" : "NACK"); /* always stop the retransmit timer when the ACK arrived */ ctimer_stop(&instance->dao_retransmit_timer); diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c new file mode 100644 index 000000000..8c9a2ff21 --- /dev/null +++ b/core/net/rpl/rpl-nbr-policy.c @@ -0,0 +1,244 @@ +/* + * 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. + */ + +#define MAX_CHILDREN (NBR_TABLE_MAX_NEIGHBORS - 3) + +static int num_parents; /* any node that are possible parents */ +static int num_children; /* all children that we have as nexthop */ +static int num_free; +static uip_ds6_nbr_t *worst_rank_nbr; /* the parent that has the worst rank */ +static rpl_rank_t worst_rank; +/*---------------------------------------------------------------------------*/ +static void +update_nbr(void) +{ + uip_ds6_nbr_t *nbr; + rpl_parent_t *parent; + int num_used; + int is_used; + rpl_rank_t rank; + + 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; + + parent = rpl_get_parent((uip_lladdr_t *)lladdr); + if(parent != NULL) { + num_parents++; + is_used++; + + 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(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 = nbr; + } + } + + /* Check if this neighbor is used as nexthop and therefor being a + RPL child. */ + if(uip_ds6_route_is_nexthop((uip_lladdr_t *)lladdr) != 0) { + is_used++; + num_children++; + } + + if(is_used == 0) { + /* This neighbor is neither parent or child and can be safely removed */ + worst_rank_nbr = nbr; + worst_rank = INFINITE_RANK; + } else if(is_used > 1) { + /* Both parent and child - this should never happen! */ + PRINTF("NBR-POLICY: *** Neighbor is both child and candidate parent: "); + PRINTLLADDR((uip_lladdr_t *)lladdr); + PRINTF("\n"); + } + + 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()); +} +/*---------------------------------------------------------------------------*/ +static int +remove_worst_nbr(void) +{ + /* we assume that it is possible to remove the worst parent at the moment */ + if(worst_rank_nbr != NULL) { + PRINTF("Removing worst ranked nbr "); + PRINTLLADDR((uip_lladdr_t*)nbr_table_get_lladdr(ds6_neighbors, worst_rank_nbr)); + PRINTF(" with rank %d\n", worst_rank); + if(uip_ds6_nbr_rm(worst_rank_nbr)) { + worst_rank_nbr = NULL; + return 1; + } + PRINTF("FAILED to remove worst ranked nbr!\n"); + return 0; + } + PRINTF("FAILED to remove worst rank nbr - no found\n"); + return 0; +} +/*---------------------------------------------------------------------------*/ +/* Called whenever we get a unicast DIS - e.g. someone that already + have this node in its table - since it is a unicast */ +static int +check_add_from_dis(uip_ipaddr_t *from) +{ + + /* do a lookup to see if it is alread there - then allow add/update */ + if(uip_ds6_nbr_lookup(from)) { + return 1; + } + update_nbr(); + if(num_free > 0) { + return 1; + } + if(num_children < MAX_CHILDREN) { + return remove_worst_nbr(); + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +check_add_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) +{ + rpl_instance_t *instance; + rpl_rank_t rank; + + /* Do a lookup to see if it is already there - then allow add/update. */ + if(uip_ds6_nbr_lookup(from)) { + return 1; + } + + update_nbr(); + + /* If there is room for this neighbor just add it. */ + if(num_free > 0) { + return 1; + } + + instance = rpl_get_instance(dio->instance_id); + if(instance == NULL || instance->current_dag == NULL) { + PRINTF("Did not find instance id: %d\n", dio->instance_id); + return 0; + } + + /* Add the new neighbor only if it is better than the preferred 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 remove_worst_nbr(); + } + + PRINTF("Found worse neighbor with new %d and old %d - NOT add to cache.\n", + rank, worst_rank); + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +check_add_from_dao(uip_ipaddr_t *from) +{ + /* Do a lookup to see if it is alread there - then allow add/update. */ + if(uip_ds6_nbr_lookup(from)) { + return 1; + } + + update_nbr(); + + /* Check if this DAO sender is not yet neighbor and there is already too + many children. */ + if(num_children >= MAX_CHILDREN) { + PRINTF("Can not add another child - already at max.\n"); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +const struct nbr_policy rpl_nbr_policy = { + check_add_from_dis, + check_add_from_dio, + check_add_from_dao +}; +/*---------------------------------------------------------------------------*/ +/** @}*/ diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index 5a7a9be94..0eecca0e0 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -124,8 +124,17 @@ #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 @@ -260,6 +269,24 @@ typedef struct rpl_stats rpl_stats_t; extern rpl_stats_t rpl_stats; #endif + +struct nbr_policy { + /** check if it is ok to add a nbr via UC DIS - positive => ok */ + int (* check_add_from_dis)(uip_ipaddr_t *from); + int (* check_add_from_dio)(uip_ipaddr_t *from, rpl_dio_t *dio); + int (* check_add_from_dao)(uip_ipaddr_t *from); +}; + + +#ifdef RPL_CONF_NBR_POLICY +#define RPL_NBR_POLICY RPL_CONF_NBR_POLICY +#else /* RPL_CONF_NBR_POLICY */ +#define RPL_NBR_POLICY rpl_nbr_policy +#endif /* RPL_CONF_NBR_POLICY */ + +extern const struct nbr_policy RPL_NBR_POLICY; + + /*---------------------------------------------------------------------------*/ /* RPL macros. */ @@ -280,6 +307,7 @@ void dao_output(rpl_parent_t *, uint8_t lifetime); void dao_output_target(rpl_parent_t *, uip_ipaddr_t *, uint8_t lifetime); void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t, uint8_t); void rpl_icmp6_register_handlers(void); +uip_ds6_nbr_t *rpl_icmp6_update_nbr_table(uip_ipaddr_t *from); /* RPL logic functions. */ void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index da5822757..90b434102 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -238,7 +238,6 @@ 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; */ PRINTF("RPL: Added a route to "); PRINT6ADDR(prefix); From f4255fad0fa548dda48c76725aa34f83295d7ab5 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 20 Aug 2015 17:13:46 +0200 Subject: [PATCH 05/30] updated rpl-udp example with scalability test --- examples/ipv6/rpl-udp/Makefile | 3 +- examples/ipv6/rpl-udp/project-conf.h | 59 ++ examples/ipv6/rpl-udp/rpl-udp-scale.csc | 729 ++++++++++++++++++++++++ examples/ipv6/rpl-udp/rpl-udp.csc | 167 +++++- examples/ipv6/rpl-udp/udp-client.c | 76 ++- examples/ipv6/rpl-udp/udp-server.c | 3 +- 6 files changed, 1009 insertions(+), 28 deletions(-) create mode 100644 examples/ipv6/rpl-udp/project-conf.h create mode 100644 examples/ipv6/rpl-udp/rpl-udp-scale.csc 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.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. From fa1b70b723f2eb188fa8a4ece19f801b3d0c2bef Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Mon, 24 Aug 2015 11:13:05 +0200 Subject: [PATCH 06/30] added configuration of DAO route refresh for broadcast DIOs --- core/net/rpl/rpl-icmp6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index b0ab53de4..e043b87a2 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -515,7 +515,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. */ From cd98b8b40ec6b238c4faf28b7f72038ec248851d Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Mon, 24 Aug 2015 11:42:50 +0200 Subject: [PATCH 07/30] added periodic debug printout of number of used neighbors and routes --- core/net/rpl/rpl-nbr-policy.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c index 8c9a2ff21..34e67f946 100644 --- a/core/net/rpl/rpl-nbr-policy.c +++ b/core/net/rpl/rpl-nbr-policy.c @@ -68,6 +68,18 @@ static int num_free; static uip_ds6_nbr_t *worst_rank_nbr; /* the parent that has the worst rank */ static rpl_rank_t worst_rank; /*---------------------------------------------------------------------------*/ +#if DEBUG == DEBUG_FULL +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) { @@ -77,6 +89,14 @@ update_nbr(void) 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; From 60dc6503e585e5833410e308d3493052577f9a3b Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Mon, 24 Aug 2015 15:10:14 +0200 Subject: [PATCH 08/30] disabled DAO ACK and configured for only one DAG per instance to save memory for er-example --- examples/er-rest-example/project-conf.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/er-rest-example/project-conf.h b/examples/er-rest-example/project-conf.h index 53662619a..3d894a5d4 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,10 @@ #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 + /* Enable client-side support for COAP observe */ #define COAP_OBSERVE_CLIENT 1 #endif /* __PROJECT_ERBIUM_CONF_H__ */ From 1d92359e72adc44ec32e0e8a9987fd2a6b27ffb7 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Mon, 24 Aug 2015 15:27:38 +0200 Subject: [PATCH 09/30] Replaced MRHof with OF-0 for getting code-size down for er-example --- examples/er-rest-example/project-conf.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/er-rest-example/project-conf.h b/examples/er-rest-example/project-conf.h index 3d894a5d4..adcb75ee1 100644 --- a/examples/er-rest-example/project-conf.h +++ b/examples/er-rest-example/project-conf.h @@ -100,6 +100,9 @@ #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__ */ From 37c5f741e91b1f1ab5fe6f5089dcc442009ce5a0 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Mon, 24 Aug 2015 16:22:07 +0200 Subject: [PATCH 10/30] removed viztool usage of learned-from routing state that was removed --- platform/cc2530dk/viztool.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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; From ad0e624d01637072d23bb4985f32fe5320b179ca Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Mon, 24 Aug 2015 20:49:50 +0200 Subject: [PATCH 11/30] increased number of routes in root node so that it can hold all routes in the simulation --- regression-tests/12-rpl/04-rpl-large-network.csc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regression-tests/12-rpl/04-rpl-large-network.csc b/regression-tests/12-rpl/04-rpl-large-network.csc index 8b3ca0d8a..88d3774bf 100644 --- a/regression-tests/12-rpl/04-rpl-large-network.csc +++ b/regression-tests/12-rpl/04-rpl-large-network.csc @@ -1,3 +1,4 @@ +<<<<<<< 1d90b9290e293eedcb6451dd86c474ec168f688c [APPS_DIR]/mrm @@ -7058,4 +7059,3 @@ while(true) { 43 - From 01930d4a649b7628a6c4917ad3f4b31bacc31b2c Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 25 Aug 2015 09:05:14 +0200 Subject: [PATCH 12/30] changed default configuration of RPL route lifetime --- core/net/rpl/rpl-conf.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index 831765974..baba6aa6c 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 From be81d1d2c60e96d42a52894cec1dba4887e3da75 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 27 Aug 2015 20:07:13 +0200 Subject: [PATCH 13/30] added uip_clear_buf to avoid the risk of sending received packets --- core/net/rpl/rpl-icmp6.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index e043b87a2..5233c1fdd 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -1084,6 +1084,7 @@ dao_ack_input(void) instance = rpl_get_instance(instance_id); if(instance == NULL) { + uip_clear_buf(); return; } @@ -1092,6 +1093,7 @@ dao_ack_input(void) /* not a known instance - did we switch?? */ // PRINTF("RPL: Received a DAO ACK from a not joined instance: %d", // instance_id); + uip_clear_buf(); return; } @@ -1099,7 +1101,6 @@ dao_ack_input(void) sequence, instance->my_dao_seqno, status); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); -#endif /* DEBUG */ if(sequence == instance->my_dao_seqno) { PRINTF("RPL: DAO %s for me!\n", status < 128 ? "ACK" : "NACK"); From 444015df675dcdab22ed5043c4085b3932bfb7d9 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Sun, 20 Sep 2015 21:02:30 +0200 Subject: [PATCH 14/30] refactored the rpl-nbr-policy to be called from nbr-table module --- core/contiki-default-conf.h | 7 ++ core/net/ipv6/uip-ds6-nbr.c | 6 +- core/net/ipv6/uip-ds6-nbr.h | 6 +- core/net/ipv6/uip-ds6-route.c | 3 +- core/net/llsec/noncoresec/noncoresec.c | 2 +- core/net/mac/phase.c | 2 +- core/net/nbr-table.c | 115 +++++++++++++++++-------- core/net/nbr-table.h | 13 ++- core/net/rpl/rpl-dag.c | 25 +++--- core/net/rpl/rpl-icmp6.c | 50 ++++++----- core/net/rpl/rpl-nbr-policy.c | 109 ++++++++++------------- core/net/rpl/rpl-private.h | 19 +--- core/net/rpl/rpl-timers.c | 2 + 13 files changed, 198 insertions(+), 161 deletions(-) diff --git a/core/contiki-default-conf.h b/core/contiki-default-conf.h index 0083f7e10..7b001bd58 100644 --- a/core/contiki-default-conf.h +++ b/core/contiki-default-conf.h @@ -148,6 +148,13 @@ #define UIP_CONF_IPV6_RPL 1 #endif /* UIP_CONF_IPV6_RPL */ +/* If RPL is enabled also enable the RPL NBR Policy */ +#if UIP_CONF_IPV6_RPL +#ifndef NBR_TABLE_FIND_REMOVABLE +#define NBR_TABLE_FIND_REMOVABLE rpl_nbr_policy_find_removable +#endif /* NBR_TABLE_FIND_REMOVABLE */ +#endif /* UIP_CONF_IPV6_RPL */ + /* UIP_CONF_MAX_ROUTES specifies the maximum number of routes that each node will be able to handle. */ #ifndef UIP_CONF_MAX_ROUTES diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index 5905993a5..b8666a14a 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -79,9 +79,11 @@ uip_ds6_neighbors_init(void) /*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, - uint8_t isrouter, uint8_t state) + uint8_t isrouter, uint8_t state, nbr_table_reason_t reason, + void *data) { - uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr); + uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr + ,reason, data); if(nbr) { uip_ipaddr_copy(&nbr->ipaddr, ipaddr); #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER diff --git a/core/net/ipv6/uip-ds6-nbr.h b/core/net/ipv6/uip-ds6-nbr.h index b0dd84d4a..2f3a51d28 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -86,8 +86,10 @@ typedef struct uip_ds6_nbr { void uip_ds6_neighbors_init(void); /** \brief Neighbor Cache basic routines */ -uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, - uint8_t isrouter, uint8_t state); +uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, + const uip_lladdr_t *lladdr, + uint8_t isrouter, uint8_t state, + nbr_table_reason_t reason, void *data); int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); const uip_lladdr_t *uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr); const uip_ipaddr_t *uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr); diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 3113986a1..21ce38f64 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -348,7 +348,8 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, initialize this pointer with the list of routing entries that are attached to this neighbor. */ routes = nbr_table_add_lladdr(nbr_routes, - (linkaddr_t *)nexthop_lladdr); + (linkaddr_t *)nexthop_lladdr, + NBR_TABLE_REASON_ROUTE, NULL); if(routes == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ diff --git a/core/net/llsec/noncoresec/noncoresec.c b/core/net/llsec/noncoresec/noncoresec.c index e18a7d734..860f7e613 100644 --- a/core/net/llsec/noncoresec/noncoresec.c +++ b/core/net/llsec/noncoresec/noncoresec.c @@ -188,7 +188,7 @@ parse(void) info = nbr_table_get_from_lladdr(anti_replay_table, sender); if(!info) { - info = nbr_table_add_lladdr(anti_replay_table, sender); + info = nbr_table_add_lladdr(anti_replay_table, sender, NBR_TABLE_REASON_LLSEC, NULL); if(!info) { PRINTF("noncoresec: could not get nbr_table_item\n"); return FRAMER_FAILED; diff --git a/core/net/mac/phase.c b/core/net/mac/phase.c index 47b7e7cf3..d7ded2428 100644 --- a/core/net/mac/phase.c +++ b/core/net/mac/phase.c @@ -122,7 +122,7 @@ phase_update(const linkaddr_t *neighbor, rtimer_clock_t time, } else { /* No matching phase was found, so we allocate a new one. */ if(mac_status == MAC_TX_OK && e == NULL) { - e = nbr_table_add_lladdr(nbr_phase, neighbor); + e = nbr_table_add_lladdr(nbr_phase, neighbor, NBR_TABLE_REASON_MAC, NULL); if(e) { e->time = time; #if PHASE_DRIFT_CORRECT diff --git a/core/net/nbr-table.c b/core/net/nbr-table.c index 6b990a020..42597c598 100644 --- a/core/net/nbr-table.c +++ b/core/net/nbr-table.c @@ -47,11 +47,20 @@ static void handle_periodic_timer(void *ptr); static struct ctimer periodic_timer; static uint8_t initialized = 0; +static void print_table(); #define PRINTF(...) printf(__VA_ARGS__) #else #define PRINTF(...) #endif +/* This is the callback function that will be called when there is a + * nbr-policy active + **/ +#ifdef NBR_TABLE_FIND_REMOVABLE +const linkaddr_t *NBR_TABLE_FIND_REMOVABLE(nbr_table_reason_t reason, void *data); +#endif /* NBR_TABLE_FIND_REMOVABLE */ + + /* List of link-layer addresses of the neighbors, used as key in the tables */ typedef struct nbr_table_key { struct nbr_table_key *next; @@ -170,7 +179,7 @@ nbr_set_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item, int val } /*---------------------------------------------------------------------------*/ static nbr_table_key_t * -nbr_table_allocate(void) +nbr_table_allocate(nbr_table_reason_t reason, void *data) { nbr_table_key_t *key; int least_used_count = 0; @@ -179,39 +188,66 @@ nbr_table_allocate(void) key = memb_alloc(&neighbor_addr_mem); if(key != NULL) { return key; - } else { /* No more space, try to free a neighbor. - * The replacement policy is the following: remove neighbor that is: - * (1) not locked - * (2) used by fewest tables - * (3) oldest (the list is ordered by insertion time) - * */ - /* Get item from first key */ - key = list_head(nbr_table_keys); - while(key != NULL) { - int item_index = index_from_key(key); - int locked = locked_map[item_index]; - /* Never delete a locked item */ - if(!locked) { - int used = used_map[item_index]; - int used_count = 0; - /* Count how many tables are using this item */ - while(used != 0) { - if((used & 1) == 1) { - used_count++; - } - used >>= 1; - } - /* Find least used item */ - if(least_used_key == NULL || used_count < least_used_count) { - least_used_key = key; - least_used_count = used_count; - if(used_count == 0) { /* We won't find any least used item */ - break; - } - } + } else { +#ifdef NBR_TABLE_FIND_REMOVABLE + const linkaddr_t *lladdr; + lladdr = NBR_TABLE_FIND_REMOVABLE(reason, data); + if(lladdr == NULL) { + /* Nothing found that can be deleted - return NULL to indicate failure */ + PRINTF("*** Not removing entry to allocate new\n"); + return NULL; + } else { + /* used least_used_key to indicate what is the least useful entry */ + int index; + int locked; + if((index = index_from_lladdr(lladdr)) != -1) { + least_used_key = key_from_index(index); + locked = locked_map[index]; + } + /* Allow delete of locked item? */ + if(least_used_key != NULL && locked) { + PRINTF("Deleting locked item!\n"); + locked_map[index] = 0; } - key = list_item_next(key); } +#endif /* NBR_TABLE_FIND_REMOVABLE */ + + if(least_used_key == NULL) { + /* No more space, try to free a neighbor. + * The replacement policy is the following: remove neighbor that is: + * (1) not locked + * (2) used by fewest tables + * (3) oldest (the list is ordered by insertion time) + * */ + /* Get item from first key */ + key = list_head(nbr_table_keys); + while(key != NULL) { + int item_index = index_from_key(key); + int locked = locked_map[item_index]; + /* Never delete a locked item */ + if(!locked) { + int used = used_map[item_index]; + int used_count = 0; + /* Count how many tables are using this item */ + while(used != 0) { + if((used & 1) == 1) { + used_count++; + } + used >>= 1; + } + /* Find least used item */ + if(least_used_key == NULL || used_count < least_used_count) { + least_used_key = key; + least_used_count = used_count; + if(used_count == 0) { /* We won't find any least used item */ + break; + } + } + } + key = list_item_next(key); + } + } + if(least_used_key == NULL) { /* We haven't found any unlocked item, allocation fails */ return NULL; @@ -289,7 +325,7 @@ nbr_table_next(nbr_table_t *table, nbr_table_item_t *item) /*---------------------------------------------------------------------------*/ /* Add a neighbor indexed with its link-layer address */ nbr_table_item_t * -nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr) +nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr, nbr_table_reason_t reason, void *data) { int index; nbr_table_item_t *item; @@ -303,7 +339,7 @@ nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr) if((index = index_from_lladdr(lladdr)) == -1) { /* Neighbor not yet in table, let's try to allocate one */ - key = nbr_table_allocate(); + key = nbr_table_allocate(reason, data); /* No space available for new entry */ if(key == NULL) { @@ -327,6 +363,9 @@ nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr) memset(item, 0, table->item_size); nbr_set_bit(used_map, table, item, 1); +#if DEBUG + print_table(); +#endif return item; } /*---------------------------------------------------------------------------*/ @@ -379,7 +418,7 @@ nbr_table_get_lladdr(nbr_table_t *table, const void *item) /*---------------------------------------------------------------------------*/ #if DEBUG static void -handle_periodic_timer(void *ptr) +print_table() { int i, j; /* Printout all neighbors and which tables they are used in */ @@ -394,6 +433,12 @@ handle_periodic_timer(void *ptr) PRINTF("\n"); } } +} +/*---------------------------------------------------------------------------*/ +static void +handle_periodic_timer(void *ptr) +{ + print_table(); ctimer_reset(&periodic_timer); } #endif diff --git a/core/net/nbr-table.h b/core/net/nbr-table.h index 516901fe3..cc58c2f80 100644 --- a/core/net/nbr-table.h +++ b/core/net/nbr-table.h @@ -75,6 +75,17 @@ typedef struct nbr_table { /** \brief Declaration of non-static neighbor tables */ #define NBR_TABLE_DECLARE(name) extern nbr_table_t *name +typedef enum { + NBR_TABLE_REASON_UNDEFINED, + NBR_TABLE_REASON_RPL_DIO, + NBR_TABLE_REASON_RPL_DAO, + NBR_TABLE_REASON_RPL_DIS, + NBR_TABLE_REASON_ROUTE, + NBR_TABLE_REASON_IPV6_ND, + NBR_TABLE_REASON_MAC, + NBR_TABLE_REASON_LLSEC +} nbr_table_reason_t; + /** \name Neighbor tables: register and loop through table elements */ /** @{ */ int nbr_table_register(nbr_table_t *table, nbr_table_callback *callback); @@ -84,7 +95,7 @@ nbr_table_item_t *nbr_table_next(nbr_table_t *table, nbr_table_item_t *item); /** \name Neighbor tables: add and get data */ /** @{ */ -nbr_table_item_t *nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr); +nbr_table_item_t *nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr, nbr_table_reason_t reason, void *data); nbr_table_item_t *nbr_table_get_from_lladdr(nbr_table_t *table, const linkaddr_t *lladdr); /** @} */ diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 79f83a84e..9d32c2773 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -634,8 +634,9 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) PRINT6ADDR(addr); PRINTF("\n"); if(lladdr != NULL) { - /* Add parent in rpl_parents */ - p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr); + /* Add parent in rpl_parents - again this is due to DIO */ + p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr, + NBR_TABLE_REASON_RPL_DIO, dio); if(p == NULL) { PRINTF("RPL: rpl_add_parent p NULL\n"); } else { @@ -1028,7 +1029,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_set_default_route(instance, from); if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { - rpl_schedule_dao_immediately(instance); + rpl_schedule_dao(instance); } else { PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); } @@ -1255,18 +1256,14 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) static int add_nbr_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { - /* check if it is ok to add this nbr based on this DIO */ - if(RPL_NBR_POLICY.check_add_from_dio(from, dio)) { - /* add this to the neighbor cache if not already there */ - if(rpl_icmp6_update_nbr_table(from) == NULL) { - PRINTF("RPL: Out of memory, dropping DIO from "); - PRINT6ADDR(from); - PRINTF("\n"); - return 0; - } - return 1; + /* add this to the neighbor cache if not already there */ + if(rpl_icmp6_update_nbr_table(from, NBR_TABLE_REASON_RPL_DIO, dio) == NULL) { + PRINTF("RPL: Out of memory, dropping DIO from "); + PRINT6ADDR(from); + PRINTF("\n"); + return 0; } - return 0; + return 1; } /*---------------------------------------------------------------------------*/ void diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 5233c1fdd..83dd71897 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -182,14 +182,14 @@ set16(uint8_t *buffer, int pos, uint16_t value) } /*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * -rpl_icmp6_update_nbr_table(uip_ipaddr_t *from) +rpl_icmp6_update_nbr_table(uip_ipaddr_t *from, nbr_table_reason_t reason, void *data) { uip_ds6_nbr_t *nbr; if((nbr = uip_ds6_nbr_lookup(from)) == NULL) { if((nbr = uip_ds6_nbr_add(from, (uip_lladdr_t *) packetbuf_addr(PACKETBUF_ADDR_SENDER), - 0, NBR_REACHABLE)) != NULL) { + 0, NBR_REACHABLE, reason, data)) != NULL) { PRINTF("RPL: Neighbor added to neighbor cache "); PRINT6ADDR(from); PRINTF(", "); @@ -231,19 +231,18 @@ dis_input(void) } else { #endif /* !RPL_LEAF_ONLY */ /* Check if this neighbor should be added according to the policy. */ - if(RPL_NBR_POLICY.check_add_from_dis(&UIP_IP_BUF->srcipaddr)) { - /* Add this to the neighbor cache if not already there */ - if(rpl_icmp6_update_nbr_table(&UIP_IP_BUF->srcipaddr) == NULL) { - PRINTF("RPL: Out of Memory, not sending unicast DIO, DIS from "); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - return; - } - PRINTF("RPL: Unicast DIS, reply to sender\n"); - dio_output(instance, &UIP_IP_BUF->srcipaddr); - } + if(rpl_icmp6_update_nbr_table(&UIP_IP_BUF->srcipaddr, + NBR_TABLE_REASON_RPL_DIS, NULL) == NULL) { + PRINTF("RPL: Out of Memory, not sending unicast DIO, DIS from "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + } else { + PRINTF("RPL: Unicast DIS, reply to sender\n"); + dio_output(instance, &UIP_IP_BUF->srcipaddr); + } + /* } */ } } } @@ -806,18 +805,18 @@ dao_input(void) PRINTF("RPL: adding DAO route\n"); - /* Check if we should add another neighbor based on DAO. */ - if(!RPL_NBR_POLICY.check_add_from_dao(&dao_sender_addr)) { - /* Do not add the neighbor. */ - return; - } /* Update and add neighbor - if no room - fail. */ - if((nbr = rpl_icmp6_update_nbr_table(&dao_sender_addr)) == NULL) { + if((nbr = rpl_icmp6_update_nbr_table(&dao_sender_addr, NBR_TABLE_REASON_RPL_DAO, NULL)) == NULL) { PRINTF("RPL: Out of Memory, dropping DAO from "); PRINT6ADDR(&dao_sender_addr); PRINTF(", "); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTF("\n"); + if(flags & RPL_DAO_K_FLAG) { + /* signal the failure to add the node */ + dao_ack_output(instance, &dao_sender_addr, sequence, + RPL_DAO_ACK_UNABLE_TO_ACCEPT); + } goto discard; } @@ -931,7 +930,9 @@ handle_dao_retransmission(void *ptr) return; } - ctimer_set(&instance->dao_retransmit_timer, RPL_DAO_RETRANSMISSION_TIMEOUT, + ctimer_set(&instance->dao_retransmit_timer, + RPL_DAO_RETRANSMISSION_TIMEOUT / 2 + + (random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT / 2)), handle_dao_retransmission, parent); instance->my_dao_transmissions++; @@ -1079,6 +1080,7 @@ dao_ack_input(void) buffer = UIP_ICMP_PAYLOAD; + instance_id = buffer[0]; sequence = buffer[2]; status = buffer[3]; @@ -1131,7 +1133,9 @@ dao_ack_input(void) if(nexthop == NULL) { PRINTF("No next hop to fwd DAO ACK to\n"); } else { - PRINTF("Fwd DAO ACK\n"); + PRINTF("Fwd DAO ACK to:"); + PRINT6ADDR(nexthop); + PRINTF("\n"); buffer[2] = re->state.dao_seqno_in; uip_icmp6_send(nexthop, ICMP6_RPL, RPL_CODE_DAO_ACK, 4); } diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c index 34e67f946..51d0df8db 100644 --- a/core/net/rpl/rpl-nbr-policy.c +++ b/core/net/rpl/rpl-nbr-policy.c @@ -49,7 +49,7 @@ #include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6-route.h" -#define DEBUG DEBUG_NONE +#define DEBUG DEBUG_FULL #include "net/ip/uip-debug.h" /* @@ -58,14 +58,18 @@ * - max X children (nexthops) * - max Y "best parents" * => at least MAX_NBRS - (Y + X + 1) free slots for other. + * + * NOTE: this policy assumes that all neighbors end up being IPv6 + * neighbors and are not only MAC neighbors. */ #define MAX_CHILDREN (NBR_TABLE_MAX_NEIGHBORS - 3) +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) static int num_parents; /* any node that are possible parents */ static int num_children; /* all children that we have as nexthop */ static int num_free; -static uip_ds6_nbr_t *worst_rank_nbr; /* the parent that has the worst rank */ +static linkaddr_t *worst_rank_nbr; /* the parent that has the worst rank */ static rpl_rank_t worst_rank; /*---------------------------------------------------------------------------*/ #if DEBUG == DEBUG_FULL @@ -124,8 +128,12 @@ update_nbr(void) parent->dag->instance != NULL && (rank = parent->dag->instance->of->calculate_rank(parent, 0)) > worst_rank) { /* This is the worst-rank neighbor - this is a good candidate for removal */ - worst_rank = rank; - worst_rank_nbr = nbr; + if(uip_ds6_route_is_nexthop((uip_lladdr_t *)lladdr) == 0) { + worst_rank = rank; + worst_rank_nbr = lladdr; + } else { + printf("*** Can not use this as worst rank as it is a next hop\n"); + } } } @@ -138,10 +146,9 @@ update_nbr(void) if(is_used == 0) { /* This neighbor is neither parent or child and can be safely removed */ - worst_rank_nbr = nbr; + worst_rank_nbr = lladdr; worst_rank = INFINITE_RANK; } else if(is_used > 1) { - /* Both parent and child - this should never happen! */ PRINTF("NBR-POLICY: *** Neighbor is both child and candidate parent: "); PRINTLLADDR((uip_lladdr_t *)lladdr); PRINTF("\n"); @@ -157,67 +164,36 @@ update_nbr(void) num_free, num_children, num_parents, uip_ds6_route_num_routes()); } /*---------------------------------------------------------------------------*/ -static int -remove_worst_nbr(void) -{ - /* we assume that it is possible to remove the worst parent at the moment */ - if(worst_rank_nbr != NULL) { - PRINTF("Removing worst ranked nbr "); - PRINTLLADDR((uip_lladdr_t*)nbr_table_get_lladdr(ds6_neighbors, worst_rank_nbr)); - PRINTF(" with rank %d\n", worst_rank); - if(uip_ds6_nbr_rm(worst_rank_nbr)) { - worst_rank_nbr = NULL; - return 1; - } - PRINTF("FAILED to remove worst ranked nbr!\n"); - return 0; - } - PRINTF("FAILED to remove worst rank nbr - no found\n"); - return 0; -} -/*---------------------------------------------------------------------------*/ /* Called whenever we get a unicast DIS - e.g. someone that already have this node in its table - since it is a unicast */ -static int -check_add_from_dis(uip_ipaddr_t *from) +const linkaddr_t * +find_removable_dis(uip_ipaddr_t *from) { - /* do a lookup to see if it is alread there - then allow add/update */ - if(uip_ds6_nbr_lookup(from)) { - return 1; - } update_nbr(); if(num_free > 0) { - return 1; + printf("num-free > 0 = %d", num_free); + printf("**** Should remove unused elements but can not... \n"); + /* return 1; */ } if(num_children < MAX_CHILDREN) { - return remove_worst_nbr(); + return worst_rank_nbr; } - return 0; + return NULL; } /*---------------------------------------------------------------------------*/ -static int -check_add_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) +const linkaddr_t * +find_removable_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { rpl_instance_t *instance; rpl_rank_t rank; - /* Do a lookup to see if it is already there - then allow add/update. */ - if(uip_ds6_nbr_lookup(from)) { - return 1; - } - update_nbr(); - /* If there is room for this neighbor just add it. */ - if(num_free > 0) { - return 1; - } - instance = rpl_get_instance(dio->instance_id); if(instance == NULL || instance->current_dag == NULL) { PRINTF("Did not find instance id: %d\n", dio->instance_id); - return 0; + return NULL; } /* Add the new neighbor only if it is better than the preferred parent. */ @@ -227,38 +203,43 @@ check_add_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) PRINTF("Found better neighbor %d < %d - add to cache...\n", rank, worst_rank); - return remove_worst_nbr(); + return worst_rank_nbr; } PRINTF("Found worse neighbor with new %d and old %d - NOT add to cache.\n", rank, worst_rank); - return 0; + return NULL; } /*---------------------------------------------------------------------------*/ -static int -check_add_from_dao(uip_ipaddr_t *from) +const linkaddr_t * +find_removable_dao(uip_ipaddr_t *from) { - /* Do a lookup to see if it is alread there - then allow add/update. */ - if(uip_ds6_nbr_lookup(from)) { - return 1; - } - update_nbr(); /* Check if this DAO sender is not yet neighbor and there is already too many children. */ if(num_children >= MAX_CHILDREN) { PRINTF("Can not add another child - already at max.\n"); - return 0; + return NULL; } - - return 1; + /* remove the worst ranked nbr */ + return worst_rank_nbr; } /*---------------------------------------------------------------------------*/ -const struct nbr_policy rpl_nbr_policy = { - check_add_from_dis, - check_add_from_dio, - check_add_from_dao -}; +const linkaddr_t * +rpl_nbr_policy_find_removable(nbr_table_reason_t reason,void * data) { + /* When we get the DIO/DAO/DIS we know that UIP contains the + incoming packet */ + switch(reason) { + case NBR_TABLE_REASON_RPL_DIO: + return find_removable_dio(&UIP_IP_BUF->srcipaddr, data); + case NBR_TABLE_REASON_RPL_DAO: + return find_removable_dao(&UIP_IP_BUF->srcipaddr); + case NBR_TABLE_REASON_RPL_DIS: + return find_removable_dis(&UIP_IP_BUF->srcipaddr); + default: + return NULL; + } +} /*---------------------------------------------------------------------------*/ /** @}*/ diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index 0eecca0e0..017efb474 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -270,22 +270,6 @@ typedef struct rpl_stats rpl_stats_t; extern rpl_stats_t rpl_stats; #endif -struct nbr_policy { - /** check if it is ok to add a nbr via UC DIS - positive => ok */ - int (* check_add_from_dis)(uip_ipaddr_t *from); - int (* check_add_from_dio)(uip_ipaddr_t *from, rpl_dio_t *dio); - int (* check_add_from_dao)(uip_ipaddr_t *from); -}; - - -#ifdef RPL_CONF_NBR_POLICY -#define RPL_NBR_POLICY RPL_CONF_NBR_POLICY -#else /* RPL_CONF_NBR_POLICY */ -#define RPL_NBR_POLICY rpl_nbr_policy -#endif /* RPL_CONF_NBR_POLICY */ - -extern const struct nbr_policy RPL_NBR_POLICY; - /*---------------------------------------------------------------------------*/ /* RPL macros. */ @@ -307,7 +291,8 @@ void dao_output(rpl_parent_t *, uint8_t lifetime); void dao_output_target(rpl_parent_t *, uip_ipaddr_t *, uint8_t lifetime); void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t, uint8_t); void rpl_icmp6_register_handlers(void); -uip_ds6_nbr_t *rpl_icmp6_update_nbr_table(uip_ipaddr_t *from); +uip_ds6_nbr_t *rpl_icmp6_update_nbr_table(uip_ipaddr_t *from, + nbr_table_reason_t r, void *data); /* RPL logic functions. */ void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index ac993691d..158f5fd74 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -224,6 +224,8 @@ set_dao_lifetime_timer(rpl_instance_t *instance) expiration_time = (clock_time_t)instance->default_lifetime * (clock_time_t)instance->lifetime_unit * CLOCK_SECOND / 2; + /* make the time for the re registration be betwen 1/2 - 3/4 of lifetime */ + expiration_time = expiration_time + (random_rand() % (expiration_time / 2)); PRINTF("RPL: Scheduling DAO lifetime timer %u ticks in the future\n", (unsigned)expiration_time); ctimer_set(&instance->dao_lifetime_timer, expiration_time, From 4246a8fbe63231518373325083a138b7c49e7581 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Sun, 20 Sep 2015 21:17:32 +0200 Subject: [PATCH 15/30] updated more nbr_add calls --- core/net/ip/tcpip.c | 2 +- core/net/ipv6/uip-nd6.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) 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-nd6.c b/core/net/ipv6/uip-nd6.c index 143cfe369..ffad6260e 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -201,9 +201,8 @@ ns_input(void) #endif /*UIP_CONF_IPV6_CHECKS */ nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); 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 +633,17 @@ 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_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, + nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, 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 +872,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) { From baa8f3c6f5a1407c5b38059a5c5aba20153c9fa9 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 22 Sep 2015 20:13:31 +0200 Subject: [PATCH 16/30] minor fixes to the simulation files --- .../21-large-rpl/code/node/client.c | 20 ++++++-- .../21-large-rpl/code/router/router.c | 46 ++++++++++++++++++- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/regression-tests/21-large-rpl/code/node/client.c b/regression-tests/21-large-rpl/code/node/client.c index 386f18529..3616c1aad 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,19 @@ 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_link()) { + printf("#A color=green\n"); + http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, + callback, NULL); + connect = 0; + } } PROCESS_END(); 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(); From ee65a3982cb8420ab5cde4a35fbf3d2a7c89c9c9 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 22 Sep 2015 20:14:29 +0200 Subject: [PATCH 17/30] configure short routing lifetime in the RPL ROOT / router --- regression-tests/21-large-rpl/code/router/project-conf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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..bec41cd5e 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 5 From 1fcef0f90df20a19dd386aef6ce83f2a5beaa901 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 22 Sep 2015 21:01:55 +0200 Subject: [PATCH 18/30] added function for checking downward route and added configuration for DAO NACK repair - default off --- core/net/rpl/rpl-conf.h | 11 +++++++++++ core/net/rpl/rpl-dag.c | 6 ++++++ core/net/rpl/rpl-icmp6.c | 26 ++++++++++++++++++++++++++ core/net/rpl/rpl-nbr-policy.c | 4 ++-- core/net/rpl/rpl.h | 8 ++++++++ 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index baba6aa6c..6822ff550 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -245,6 +245,17 @@ #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 diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 9d32c2773..034678ff5 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -1156,6 +1156,9 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) RPL_STAT(rpl_stats.global_repairs++); } + +void rpl_set_downward_link(uint8_t link); + /*---------------------------------------------------------------------------*/ void rpl_local_repair(rpl_instance_t *instance) @@ -1174,6 +1177,9 @@ rpl_local_repair(rpl_instance_t *instance) } } + /* no downward link anymore */ + rpl_set_downward_link(0); + rpl_reset_dio_timer(instance); /* Request refresh of DAO registrations next DIO */ RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 83dd71897..af7a05d67 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -89,6 +89,7 @@ void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); #endif static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; +static uint8_t downward = 0; extern rpl_of_t RPL_OF; @@ -102,6 +103,19 @@ 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); /*---------------------------------------------------------------------------*/ + +void +rpl_set_downward_link(uint8_t link) +{ + downward = link; +} + +int +rpl_has_downward_link() +{ + return downward; +} + #if RPL_WITH_DAO_ACK static uip_ds6_route_t * find_route_entry_by_dao_ack(uint8_t seq) @@ -967,6 +981,13 @@ dao_output(rpl_parent_t *parent, uint8_t lifetime) instance->my_dao_transmissions = 1; ctimer_set(&instance->dao_retransmit_timer, RPL_DAO_RETRANSMISSION_TIMEOUT, handle_dao_retransmission, parent); + if(lifetime == RPL_ZERO_LIFETIME) { + rpl_set_downward_link(0); + } +#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 */ + rpl_set_downward_link(lifetime != RPL_ZERO_LIFETIME); #endif /* RPL_WITH_DAO_ACK */ } /*---------------------------------------------------------------------------*/ @@ -1107,6 +1128,8 @@ dao_ack_input(void) if(sequence == instance->my_dao_seqno) { PRINTF("RPL: DAO %s for me!\n", status < 128 ? "ACK" : "NACK"); + rpl_set_downward_link(status < 128); + /* always stop the retransmit timer when the ACK arrived */ ctimer_stop(&instance->dao_retransmit_timer); @@ -1115,11 +1138,14 @@ dao_ack_input(void) 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 should be forwarded to another recently registered route */ uip_ds6_route_t *re; diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c index 51d0df8db..7b0e28ff1 100644 --- a/core/net/rpl/rpl-nbr-policy.c +++ b/core/net/rpl/rpl-nbr-policy.c @@ -49,7 +49,7 @@ #include "net/ipv6/uip-ds6-nbr.h" #include "net/ipv6/uip-ds6-route.h" -#define DEBUG DEBUG_FULL +#define DEBUG DEBUG_NONE #include "net/ip/uip-debug.h" /* @@ -63,7 +63,7 @@ * neighbors and are not only MAC neighbors. */ -#define MAX_CHILDREN (NBR_TABLE_MAX_NEIGHBORS - 3) +#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 */ diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index b7d7757c2..dfc081d4b 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -300,5 +300,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 link or not. + * + * \retval 1 if we have a downward link, 0 if not. + */ +int rpl_has_downward_link(void); + /*---------------------------------------------------------------------------*/ #endif /* RPL_H */ From 13b8c04c6f603030b484ba455d690719f49e86fa Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 22 Sep 2015 22:12:06 +0200 Subject: [PATCH 19/30] fixed so that nbr policy for RPL Root do not save room for parents --- core/net/rpl/rpl-icmp6.c | 2 +- core/net/rpl/rpl-nbr-policy.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index af7a05d67..6ff0dcfee 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -820,7 +820,7 @@ dao_input(void) PRINTF("RPL: adding DAO route\n"); /* Update and add neighbor - if no room - fail. */ - if((nbr = rpl_icmp6_update_nbr_table(&dao_sender_addr, NBR_TABLE_REASON_RPL_DAO, NULL)) == NULL) { + 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(", "); diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c index 7b0e28ff1..9c750a7e0 100644 --- a/core/net/rpl/rpl-nbr-policy.c +++ b/core/net/rpl/rpl-nbr-policy.c @@ -62,7 +62,6 @@ * 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]) @@ -212,13 +211,21 @@ find_removable_dio(uip_ipaddr_t *from, rpl_dio_t *dio) } /*---------------------------------------------------------------------------*/ const linkaddr_t * -find_removable_dao(uip_ipaddr_t *from) +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_CHILDREN) { + if(num_children >= max) { PRINTF("Can not add another child - already at max.\n"); return NULL; } @@ -234,7 +241,7 @@ rpl_nbr_policy_find_removable(nbr_table_reason_t reason,void * data) { 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); + return find_removable_dao(&UIP_IP_BUF->srcipaddr, data); case NBR_TABLE_REASON_RPL_DIS: return find_removable_dis(&UIP_IP_BUF->srcipaddr); default: From dae21fcb76fbed260cd1dd7f618d40d04e5a1643 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Tue, 22 Sep 2015 23:21:03 +0200 Subject: [PATCH 20/30] made ZERO LIFETIME routes live 30 seconds instead of 60 and shortened route lifetime in travis test --- regression-tests/21-large-rpl/code/router/project-conf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 bec41cd5e..7f338deca 100644 --- a/regression-tests/21-large-rpl/code/router/project-conf.h +++ b/regression-tests/21-large-rpl/code/router/project-conf.h @@ -8,4 +8,4 @@ #define NBR_TABLE_CONF_MAX_NEIGHBORS 8 #define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 -#define RPL_CONF_DEFAULT_LIFETIME 5 +#define RPL_CONF_DEFAULT_LIFETIME 3 From 8afe3fb9b79c6b39130e52f1188c4900557e3154 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Wed, 23 Sep 2015 09:12:35 +0200 Subject: [PATCH 21/30] fixed so that DAO NACK now is either for the path or for RPL root - if from root then do not try to switch parent since that will not help --- core/net/rpl/rpl-icmp6.c | 10 +++++++--- core/net/rpl/rpl-mrhof.c | 5 ++++- core/net/rpl/rpl-private.h | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 6ff0dcfee..0851cd9a2 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -663,6 +663,7 @@ dao_input(void) int learned_from; rpl_parent_t *parent; uip_ds6_nbr_t *nbr; + int is_root; prefixlen = 0; parent = NULL; @@ -695,6 +696,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))) { @@ -829,7 +832,8 @@ dao_input(void) if(flags & RPL_DAO_K_FLAG) { /* signal the failure to add the node */ dao_ack_output(instance, &dao_sender_addr, sequence, - RPL_DAO_ACK_UNABLE_TO_ACCEPT); + is_root ? RPL_DAO_ACK_UNABLE_TO_ACCEPT_ROOT : + RPL_DAO_ACK_UNABLE_TO_ACCEPT); } goto discard; } @@ -838,11 +842,11 @@ dao_input(void) 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, - RPL_DAO_ACK_UNABLE_TO_ACCEPT); + is_root ? RPL_DAO_ACK_UNABLE_TO_ACCEPT_ROOT : + RPL_DAO_ACK_UNABLE_TO_ACCEPT); } goto discard; } diff --git a/core/net/rpl/rpl-mrhof.c b/core/net/rpl/rpl-mrhof.c index acf2b1d54..6da2ec304 100644 --- a/core/net/rpl/rpl-mrhof.c +++ b/core/net/rpl/rpl-mrhof.c @@ -122,8 +122,11 @@ reset(rpl_dag_t *dag) static void dao_ack_callback(rpl_parent_t *p, int status) { + if(status == RPL_DAO_ACK_UNABLE_TO_ACCEPT_ROOT) { + return; + } /* here we need to handle failed DAO's and other stuff */ - PRINTF("RPL: MRHOF - DAO ACK received with status: %d", status); + 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); diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index 017efb474..161cdc532 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -94,6 +94,7 @@ #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_ACCEPT_ROOT 255 /* root can not accept */ #define RPL_DAO_ACK_TIMEOUT -1 From 09c624dcd39653a26f0687805df4368d6956903c Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Fri, 2 Oct 2015 07:38:52 +0200 Subject: [PATCH 22/30] fixed clearing of state flag and avoid starting retransmission timer --- core/net/ipv6/uip-ds6-route.h | 3 +++ core/net/ipv6/uip-nd6.c | 11 ++++++----- core/net/rpl/rpl-icmp6.c | 29 +++++++++++++++-------------- core/net/rpl/rpl.c | 2 ++ 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/core/net/ipv6/uip-ds6-route.h b/core/net/ipv6/uip-ds6-route.h index 3324a8e08..7a5d805f0 100644 --- a/core/net/ipv6/uip-ds6-route.h +++ b/core/net/ipv6/uip-ds6-route.h @@ -106,6 +106,9 @@ void uip_ds6_notification_rm(struct uip_ds6_notification *n); #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) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index ffad6260e..107e66369 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -201,6 +201,8 @@ ns_input(void) #endif /*UIP_CONF_IPV6_CHECKS */ nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); 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, NBR_TABLE_REASON_IPV6_ND, NULL); } else { @@ -638,12 +640,11 @@ rs_input(void) } 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, - nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, 0, NBR_STALE, - NBR_TABLE_REASON_IPV6_ND, NULL); + 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); nbr->reachable = nbr_data.reachable; nbr->sendns = nbr_data.sendns; nbr->nscount = nbr_data.nscount; @@ -872,8 +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_TABLE_REASON_IPV6_ND, NULL); + 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/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 0851cd9a2..4320181e8 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 @@ -811,11 +812,12 @@ dao_input(void) uip_icmp6_send(rpl_get_parent_ipaddr(dag->preferred_parent), ICMP6_RPL, RPL_CODE_DAO, buffer_length); } - 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); - } + } + /* 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; } @@ -851,8 +853,9 @@ dao_input(void) goto discard; } - /* State is all zeroes, set lifetime but no need for other initialization. */ + /* set lifetime and clear NOPATH bit */ rep->state.lifetime = RPL_LIFETIME(instance, lifetime); + RPL_ROUTE_CLEAR_NOPATH_RECEIVED(rep); #if RPL_CONF_MULTICAST fwd_dao: @@ -978,15 +981,13 @@ dao_output(rpl_parent_t *parent, uint8_t lifetime) /* Sending a DAO with own prefix as target */ dao_output_target(parent, &prefix, lifetime); - /* keep track of my own sending of DAO for handling ack and loss of ack */ - instance->my_dao_seqno = dao_sequence; - #if RPL_WITH_DAO_ACK - instance->my_dao_transmissions = 1; - ctimer_set(&instance->dao_retransmit_timer, RPL_DAO_RETRANSMISSION_TIMEOUT, - handle_dao_retransmission, parent); - if(lifetime == RPL_ZERO_LIFETIME) { - rpl_set_downward_link(0); + /* keep track of my own sending of DAO for handling ack and loss of ack */ + if(lifetime != RPL_ZERO_LIFETIME) { + 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 diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 90b434102..c541463d4 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -238,6 +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); + /* 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); From ab4a0e08c7c175d317f785802176a97a760f5c8a Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Fri, 2 Oct 2015 07:41:57 +0200 Subject: [PATCH 23/30] fixed simulation files to be closer to defaults in configuration --- regression-tests/12-rpl/04-rpl-large-network.csc | 3 +-- regression-tests/21-large-rpl/code/node/client.c | 7 +++++++ regression-tests/21-large-rpl/code/router/project-conf.h | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/regression-tests/12-rpl/04-rpl-large-network.csc b/regression-tests/12-rpl/04-rpl-large-network.csc index 88d3774bf..145cad14c 100644 --- a/regression-tests/12-rpl/04-rpl-large-network.csc +++ b/regression-tests/12-rpl/04-rpl-large-network.csc @@ -1,4 +1,3 @@ -<<<<<<< 1d90b9290e293eedcb6451dd86c474ec168f688c [APPS_DIR]/mrm @@ -7058,4 +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 3616c1aad..36dc40923 100644 --- a/regression-tests/21-large-rpl/code/node/client.c +++ b/regression-tests/21-large-rpl/code/node/client.c @@ -105,6 +105,13 @@ PROCESS_THREAD(http_example_process, ev, data) 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; + } } } 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 7f338deca..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 60 -#define RPL_CONF_DEFAULT_LIFETIME 3 +/* #define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 */ +/* #define RPL_CONF_DEFAULT_LIFETIME 10 */ From 6fa3479aa89f1ed279c688cdbdd2e5622922ad21 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Wed, 18 Nov 2015 15:25:13 +0100 Subject: [PATCH 24/30] RPL: improved debug messages for No-Path DAOs Conflicts: core/net/rpl/rpl-icmp6.c --- core/net/rpl/rpl-icmp6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 4320181e8..050a894da 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -802,7 +802,7 @@ dao_input(void) uint8_t out_seq; out_seq = prepare_for_dao_fwd(sequence, rep); - PRINTF("RPL: Forwarding no-path DAO to parent - out_seq:%d", + PRINTF("RPL: Forwarding No-path DAO to parent - out_seq:%d", out_seq); PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent)); PRINTF("\n"); From 19b04098d55ebdaaa16657f0c8a643af49e9577c Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Mon, 23 Nov 2015 13:38:48 +0100 Subject: [PATCH 25/30] Improved RPL debug logs --- core/net/rpl/rpl-icmp6.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 050a894da..c7e4cbc8a 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -671,11 +671,6 @@ dao_input(void) 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; @@ -711,8 +706,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); @@ -822,7 +821,7 @@ dao_input(void) goto discard; } - PRINTF("RPL: adding DAO route\n"); + PRINTF("RPL: Adding DAO route\n"); /* 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) { @@ -897,7 +896,7 @@ fwd_dao: } if(should_ack) { - PRINTF("RPL: sending DAO ACK\n"); + PRINTF("RPL: Sending DAO ACK\n"); dao_ack_output(instance, &dao_sender_addr, sequence, RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); } @@ -1081,7 +1080,8 @@ dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix, 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)); @@ -1125,14 +1125,13 @@ dao_ack_input(void) return; } - PRINTF("RPL: Received a DAO ACK with sequence number %d (%d) and status %d from ", + 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"); if(sequence == instance->my_dao_seqno) { - PRINTF("RPL: DAO %s for me!\n", status < 128 ? "ACK" : "NACK"); - rpl_set_downward_link(status < 128); /* always stop the retransmit timer when the ACK arrived */ @@ -1152,7 +1151,7 @@ dao_ack_input(void) #endif } else { - /* this DAO should be forwarded to another recently registered route */ + /* 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) { @@ -1162,9 +1161,9 @@ dao_ack_input(void) nexthop = uip_ds6_route_nexthop(re); if(nexthop == NULL) { - PRINTF("No next hop to fwd DAO ACK to\n"); + PRINTF("RPL: No next hop to fwd DAO ACK to\n"); } else { - PRINTF("Fwd DAO ACK to:"); + PRINTF("RPL: Fwd DAO ACK to:"); PRINT6ADDR(nexthop); PRINTF("\n"); buffer[2] = re->state.dao_seqno_in; @@ -1176,7 +1175,7 @@ dao_ack_input(void) uip_ds6_route_rm(re); } } else { - PRINTF("No route entry to fwd DAO ACK to\n"); + PRINTF("RPL: No route entry to fwd DAO ACK to\n"); } } #endif /* RPL_WITH_DAO_ACK */ @@ -1190,7 +1189,7 @@ dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence, #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(" with status %d\n", status); From e1f9369a091c5c17e8ed2de3a0e3cba6d7b42786 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Mon, 23 Nov 2015 13:39:49 +0100 Subject: [PATCH 26/30] RPL DAO-ACK: move initialization of current ougoing DAO from da_output to dao_output_target_seq --- core/net/rpl/rpl-icmp6.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index c7e4cbc8a..566aa8b93 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -966,7 +966,6 @@ dao_output(rpl_parent_t *parent, uint8_t lifetime) { /* Destination Advertisement Object */ uip_ipaddr_t prefix; - rpl_instance_t *instance; if(get_global_addr(&prefix) == 0) { PRINTF("RPL: No global address set for this node - suppressing DAO\n"); @@ -976,23 +975,9 @@ dao_output(rpl_parent_t *parent, uint8_t lifetime) if(parent == NULL || parent->dag == NULL || parent->dag->instance == NULL) { return; } - instance = parent->dag->instance; /* Sending a DAO with own prefix as target */ dao_output_target(parent, &prefix, lifetime); -#if RPL_WITH_DAO_ACK - /* keep track of my own sending of DAO for handling ack and loss of ack */ - if(lifetime != RPL_ZERO_LIFETIME) { - 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 */ - rpl_set_downward_link(lifetime != RPL_ZERO_LIFETIME); -#endif /* RPL_WITH_DAO_ACK */ } /*---------------------------------------------------------------------------*/ void @@ -1089,6 +1074,19 @@ dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix, if(rpl_get_parent_ipaddr(parent) != NULL) { uip_icmp6_send(rpl_get_parent_ipaddr(parent), ICMP6_RPL, RPL_CODE_DAO, pos); +#if RPL_WITH_DAO_ACK + if(lifetime != RPL_ZERO_LIFETIME) { + /* keep track of my own sending of DAO for handling ack and loss of ack */ + 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 /* RPL_WITH_DAO_ACK */ + /* 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 */ + rpl_set_downward_link(lifetime != RPL_ZERO_LIFETIME); +#endif /* RPL_WITH_DAO_ACK */ } } /*---------------------------------------------------------------------------*/ From ffb10094ab1f81cfd4d8b0ba28063eed33ddf03e Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 18 Feb 2016 15:19:32 +0100 Subject: [PATCH 27/30] added init value of locked variable --- core/net/nbr-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/nbr-table.c b/core/net/nbr-table.c index 42597c598..ddae06fca 100644 --- a/core/net/nbr-table.c +++ b/core/net/nbr-table.c @@ -199,7 +199,7 @@ nbr_table_allocate(nbr_table_reason_t reason, void *data) } else { /* used least_used_key to indicate what is the least useful entry */ int index; - int locked; + int locked = 0; if((index = index_from_lladdr(lladdr)) != -1) { least_used_key = key_from_index(index); locked = locked_map[index]; From ee97dc4bcd4aae89f4819711d90326d1c2495990 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 18 Feb 2016 15:52:35 +0100 Subject: [PATCH 28/30] tuned configuration for rpl-collect and micaz platform --- examples/ipv6/rpl-collect/Makefile | 2 + examples/ipv6/rpl-collect/project-conf.h | 59 ++++++++++++++++++++++++ platform/micaz/contiki-conf.h | 11 +++-- 3 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 examples/ipv6/rpl-collect/project-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/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 From 12ac02650bf9af8490f1f4713b35f5ec09d4ab1a Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Thu, 18 Feb 2016 22:40:30 +0100 Subject: [PATCH 29/30] fixed a bug in nbr policy and DAO retransmission handling and added new wismote simulation --- core/net/rpl/rpl-icmp6.c | 32 +- core/net/rpl/rpl-nbr-policy.c | 25 +- .../ipv6/rpl-udp/rpl-udp-scale-wismote.csc | 721 ++++++++++++++++++ 3 files changed, 751 insertions(+), 27 deletions(-) create mode 100644 examples/ipv6/rpl-udp/rpl-udp-scale-wismote.csc diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 566aa8b93..2296f0d97 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -976,6 +976,25 @@ dao_output(rpl_parent_t *parent, uint8_t lifetime) 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 */ + rpl_set_downward_link(lifetime != RPL_ZERO_LIFETIME); +#endif /* RPL_WITH_DAO_ACK */ + /* Sending a DAO with own prefix as target */ dao_output_target(parent, &prefix, lifetime); } @@ -1074,19 +1093,6 @@ dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix, if(rpl_get_parent_ipaddr(parent) != NULL) { uip_icmp6_send(rpl_get_parent_ipaddr(parent), ICMP6_RPL, RPL_CODE_DAO, pos); -#if RPL_WITH_DAO_ACK - if(lifetime != RPL_ZERO_LIFETIME) { - /* keep track of my own sending of DAO for handling ack and loss of ack */ - 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 /* RPL_WITH_DAO_ACK */ - /* 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 */ - rpl_set_downward_link(lifetime != RPL_ZERO_LIFETIME); -#endif /* RPL_WITH_DAO_ACK */ } } /*---------------------------------------------------------------------------*/ diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c index 9c750a7e0..6f0dd9ca3 100644 --- a/core/net/rpl/rpl-nbr-policy.c +++ b/core/net/rpl/rpl-nbr-policy.c @@ -111,36 +111,33 @@ update_nbr(void) 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((uip_lladdr_t *)lladdr) != 0) { + is_used++; + num_children++; + } + parent = rpl_get_parent((uip_lladdr_t *)lladdr); if(parent != NULL) { num_parents++; - is_used++; 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(worst_rank < INFINITE_RANK && + } 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 */ - if(uip_ds6_route_is_nexthop((uip_lladdr_t *)lladdr) == 0) { - worst_rank = rank; - worst_rank_nbr = lladdr; - } else { - printf("*** Can not use this as worst rank as it is a next hop\n"); - } + worst_rank = rank; + worst_rank_nbr = lladdr; } - } - - /* Check if this neighbor is used as nexthop and therefor being a - RPL child. */ - if(uip_ds6_route_is_nexthop((uip_lladdr_t *)lladdr) != 0) { + /* add to is_used after evaluation of is_used above */ is_used++; - num_children++; } if(is_used == 0) { 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 + + + From 12a75c3e4325d960eb62bc3f7ff78b4c3b1dd667 Mon Sep 17 00:00:00 2001 From: Joakim Eriksson Date: Sat, 26 Mar 2016 20:12:52 +0100 Subject: [PATCH 30/30] fixed codestyle, improved APIs, and cleaned up comments --- core/net/ipv6/uip-ds6-nbr.c | 2 +- core/net/ipv6/uip-ds6-route.c | 9 +++- core/net/ipv6/uip-ds6-route.h | 5 ++- core/net/nbr-table.h | 2 +- core/net/rpl/rpl-dag.c | 18 ++++++-- core/net/rpl/rpl-icmp6.c | 43 ++++++++----------- core/net/rpl/rpl-mrhof.c | 8 +++- core/net/rpl/rpl-nbr-policy.c | 33 ++++++++------ core/net/rpl/rpl-of0.c | 2 + core/net/rpl/rpl-private.h | 2 +- core/net/rpl/rpl.h | 16 +++++-- .../21-large-rpl/code/node/client.c | 2 +- 12 files changed, 91 insertions(+), 51 deletions(-) diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index b8666a14a..e5c6167e5 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -83,7 +83,7 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, void *data) { uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr - ,reason, data); + , reason, data); if(nbr) { uip_ipaddr_copy(&nbr->ipaddr, ipaddr); #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 21ce38f64..043ca78d4 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -207,8 +207,15 @@ uip_ds6_route_next(uip_ds6_route_t *r) } /*---------------------------------------------------------------------------*/ int -uip_ds6_route_is_nexthop(const uip_lladdr_t *lladdr) +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; } /*---------------------------------------------------------------------------*/ diff --git a/core/net/ipv6/uip-ds6-route.h b/core/net/ipv6/uip-ds6-route.h index 7a5d805f0..6ca533c9b 100644 --- a/core/net/ipv6/uip-ds6-route.h +++ b/core/net/ipv6/uip-ds6-route.h @@ -124,6 +124,9 @@ void uip_ds6_notification_rm(struct uip_ds6_notification *n); #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); \ @@ -200,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_lladdr_t *lladdr); +int uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr); /** @} */ #endif /* UIP_DS6_ROUTE_H */ diff --git a/core/net/nbr-table.h b/core/net/nbr-table.h index cc58c2f80..88a90a46c 100644 --- a/core/net/nbr-table.h +++ b/core/net/nbr-table.h @@ -83,7 +83,7 @@ typedef enum { NBR_TABLE_REASON_ROUTE, NBR_TABLE_REASON_IPV6_ND, NBR_TABLE_REASON_MAC, - NBR_TABLE_REASON_LLSEC + NBR_TABLE_REASON_LLSEC } nbr_table_reason_t; /** \name Neighbor tables: register and loop through table elements */ diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 034678ff5..27f781bdf 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -899,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) { @@ -1157,8 +1169,6 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) RPL_STAT(rpl_stats.global_repairs++); } -void rpl_set_downward_link(uint8_t link); - /*---------------------------------------------------------------------------*/ void rpl_local_repair(rpl_instance_t *instance) @@ -1177,8 +1187,8 @@ rpl_local_repair(rpl_instance_t *instance) } } - /* no downward link anymore */ - rpl_set_downward_link(0); + /* no downward route anymore */ + instance->has_downward_route = 0; rpl_reset_dio_timer(instance); /* Request refresh of DAO registrations next DIO */ diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 2296f0d97..0f20ddb67 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -90,7 +90,6 @@ void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); #endif static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; -static uint8_t downward = 0; extern rpl_of_t RPL_OF; @@ -105,18 +104,6 @@ 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); /*---------------------------------------------------------------------------*/ -void -rpl_set_downward_link(uint8_t link) -{ - downward = link; -} - -int -rpl_has_downward_link() -{ - return downward; -} - #if RPL_WITH_DAO_ACK static uip_ds6_route_t * find_route_entry_by_dao_ack(uint8_t seq) @@ -215,8 +202,10 @@ rpl_icmp6_update_nbr_table(uip_ipaddr_t *from, nbr_table_reason_t reason, void * if(nbr != NULL) { #if UIP_ND6_SEND_NA - /* set reachable timer if we added or found the nbr entry */ + /* 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; @@ -833,7 +822,7 @@ dao_input(void) 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_ACCEPT_ROOT : + is_root ? RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT : RPL_DAO_ACK_UNABLE_TO_ACCEPT); } goto discard; @@ -846,7 +835,7 @@ dao_input(void) 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_ACCEPT_ROOT : + is_root ? RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT : RPL_DAO_ACK_UNABLE_TO_ACCEPT); } goto discard; @@ -864,8 +853,12 @@ fwd_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. */ + /* + * 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)) { @@ -992,7 +985,7 @@ dao_output(rpl_parent_t *parent, uint8_t lifetime) #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 */ - rpl_set_downward_link(lifetime != RPL_ZERO_LIFETIME); + parent->dag->instance->has_downward_route = lifetime != RPL_ZERO_LIFETIME; #endif /* RPL_WITH_DAO_ACK */ /* Sending a DAO with own prefix as target */ @@ -1122,9 +1115,7 @@ dao_ack_input(void) parent = rpl_find_parent(instance->current_dag, &UIP_IP_BUF->srcipaddr); if(parent == NULL) { - /* not a known instance - did we switch?? */ - // PRINTF("RPL: Received a DAO ACK from a not joined instance: %d", - // instance_id); + /* not a known instance - drop the packet and ignore */ uip_clear_buf(); return; } @@ -1136,7 +1127,7 @@ dao_ack_input(void) PRINTF("\n"); if(sequence == instance->my_dao_seqno) { - rpl_set_downward_link(status < 128); + instance->has_downward_route = status < 128; /* always stop the retransmit timer when the ACK arrived */ ctimer_stop(&instance->dao_retransmit_timer); @@ -1148,8 +1139,10 @@ dao_ack_input(void) #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... */ + /* + * 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 diff --git a/core/net/rpl/rpl-mrhof.c b/core/net/rpl/rpl-mrhof.c index 6da2ec304..f9ea76080 100644 --- a/core/net/rpl/rpl-mrhof.c +++ b/core/net/rpl/rpl-mrhof.c @@ -54,7 +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); @@ -63,7 +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, @@ -119,10 +123,11 @@ 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_ACCEPT_ROOT) { + if(status == RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT) { return; } /* here we need to handle failed DAO's and other stuff */ @@ -135,6 +140,7 @@ dao_ack_callback(rpl_parent_t *p, int status) 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 index 6f0dd9ca3..87849af40 100644 --- a/core/net/rpl/rpl-nbr-policy.c +++ b/core/net/rpl/rpl-nbr-policy.c @@ -72,6 +72,10 @@ 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; @@ -111,9 +115,12 @@ update_nbr(void) 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((uip_lladdr_t *)lladdr) != 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++; } @@ -123,10 +130,10 @@ update_nbr(void) 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. */ - + /* + * 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 && @@ -168,9 +175,10 @@ find_removable_dis(uip_ipaddr_t *from) update_nbr(); if(num_free > 0) { - printf("num-free > 0 = %d", num_free); - printf("**** Should remove unused elements but can not... \n"); - /* return 1; */ + /* 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; @@ -192,7 +200,7 @@ find_removable_dio(uip_ipaddr_t *from, rpl_dio_t *dio) return NULL; } - /* Add the new neighbor only if it is better than the preferred parent. */ + /* Add the new neighbor only if it is better than the worst parent. */ rank = instance->of->calculate_rank(NULL, dio->rank); if(rank < worst_rank - instance->min_hoprankinc / 2) { /* Found *great* neighbor - add! */ @@ -231,7 +239,8 @@ find_removable_dao(uip_ipaddr_t *from, rpl_instance_t *instance) } /*---------------------------------------------------------------------------*/ const linkaddr_t * -rpl_nbr_policy_find_removable(nbr_table_reason_t reason,void * data) { +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) { diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index ed76bac4b..b0a909a4d 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -55,7 +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 161cdc532..ec885eaea 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -94,7 +94,7 @@ #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_ACCEPT_ROOT 255 /* root can not accept */ +#define RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT 255 /* root can not accept */ #define RPL_DAO_ACK_TIMEOUT -1 diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index dfc081d4b..532df4b3a 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -181,11 +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); @@ -220,6 +228,8 @@ struct rpl_instance { /* 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 */ @@ -302,11 +312,11 @@ enum rpl_mode rpl_get_mode(void); /** - * Get the RPL's best guess on if we have downward link or not. + * Get the RPL's best guess on if we have downward route or not. * - * \retval 1 if we have a downward link, 0 if not. + * \retval 1 if we have a downward route from RPL Root, 0 if not. */ -int rpl_has_downward_link(void); +int rpl_has_downward_route(void); /*---------------------------------------------------------------------------*/ #endif /* RPL_H */ diff --git a/regression-tests/21-large-rpl/code/node/client.c b/regression-tests/21-large-rpl/code/node/client.c index 36dc40923..1e82e2df0 100644 --- a/regression-tests/21-large-rpl/code/node/client.c +++ b/regression-tests/21-large-rpl/code/node/client.c @@ -100,7 +100,7 @@ PROCESS_THREAD(http_example_process, ev, data) while(1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); - if(connect && rpl_has_downward_link()) { + if(connect && rpl_has_downward_route()) { printf("#A color=green\n"); http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, callback, NULL);