From a70a33337e91c4a812aa2ef31a41d5899eed0166 Mon Sep 17 00:00:00 2001 From: Eric Engel Date: Tue, 27 Mar 2012 17:56:47 +0200 Subject: [PATCH 1/2] RPL Finished, fixed some bugs, changed printf to puts, Use of Link Local addresses in RPL --- projects/test_rpl/main.c | 12 +-- sys/net/sixlowpan/rpl/rpl.c | 121 ++++++++++++++++++++-------- sys/net/sixlowpan/rpl/rpl.h | 7 +- sys/net/sixlowpan/rpl/rpl_dodag.c | 2 +- sys/net/sixlowpan/rpl/rpl_structs.h | 1 + sys/net/sixlowpan/rpl/trickle.c | 17 +++- sys/net/sixlowpan/rpl/trickle.h | 1 + sys/net/sixlowpan/sixlowip.c | 12 +-- 8 files changed, 118 insertions(+), 55 deletions(-) diff --git a/projects/test_rpl/main.c b/projects/test_rpl/main.c index ae5c2588a9..8d47641da7 100644 --- a/projects/test_rpl/main.c +++ b/projects/test_rpl/main.c @@ -17,7 +17,6 @@ void init(char *str){ char command; uint16_t r_addr; - ipv6_addr_t std_addr; int res = sscanf(str, "init %c %hu", &command, &r_addr); @@ -28,30 +27,27 @@ void init(char *str){ printf("\taddress must be an 8 bit integer\n"); } - ipv6_init_address(&std_addr, 0xABCD,0,0,0,0x1234,0xFFFF,0xFEDC,r_addr); uint8_t state; switch (command) { case 'r': - printf("INFO: Initialize as root on address \n"); - ipv6_print_addr(&std_addr); + printf("INFO: Initialize as root on address %d\n", r_addr); if (r_addr > 255) { printf("ERROR: address not an 8 bit integer\n"); return; } - state = rpl_init(TRANSCEIVER_CC1100, &std_addr); + state = rpl_init(TRANSCEIVER_CC1100, r_addr); if(state != SUCCESS){ printf("Error initializing RPL\n"); } rpl_init_root(); break; case 'n': - printf("INFO: Initialize as node on address \n"); - ipv6_print_addr(&std_addr); + printf("INFO: Initialize as node on address %d\n", r_addr); if (r_addr > 255) { printf("ERROR: address not an 8 bit integer\n"); return; } - state = rpl_init(TRANSCEIVER_CC1100, &std_addr); + state = rpl_init(TRANSCEIVER_CC1100, r_addr); if(state != SUCCESS){ printf("Error initializing RPL\n"); } diff --git a/sys/net/sixlowpan/rpl/rpl.c b/sys/net/sixlowpan/rpl/rpl.c index d6e8fd5711..fb5013dcfa 100644 --- a/sys/net/sixlowpan/rpl/rpl.c +++ b/sys/net/sixlowpan/rpl/rpl.c @@ -34,6 +34,7 @@ static struct icmpv6_hdr_t* icmp_send_buf; static struct rpl_dio_t *rpl_send_dio_buf; static struct rpl_dis_t *rpl_send_dis_buf; static struct rpl_dao_t *rpl_send_dao_buf; +static struct rpl_dao_ack_t * rpl_send_dao_ack_buf; static struct rpl_opt_dodag_conf_t * rpl_send_opt_dodag_conf_buf; static struct rpl_opt_solicited_t * rpl_send_opt_solicited_buf; static struct rpl_opt_target_t * rpl_send_opt_target_buf; @@ -45,7 +46,7 @@ static struct ipv6_hdr_t* ipv6_buf; static struct rpl_dio_t *rpl_dio_buf; static struct rpl_dis_t *rpl_dis_buf; static struct rpl_dao_t *rpl_dao_buf; -//static struct rpl_dao_ack_t * rpl_dao_ack_buf; +static struct rpl_dao_ack_t * rpl_dao_ack_buf; static struct rpl_opt_t *rpl_opt_buf; static struct rpl_opt_dodag_conf_t * rpl_opt_dodag_conf_buf; static struct rpl_opt_solicited_t * rpl_opt_solicited_buf; @@ -72,6 +73,9 @@ static struct rpl_dao_t* get_rpl_send_dao_buf(){ //return ((struct rpl_dao_t*)&(rpl_send_buffer[LLHDR_ICMPV6HDR_LEN])); return ((struct rpl_dao_t*)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN])); } +static struct rpl_dao_ack_t* get_rpl_send_dao_ack_buf(){ + return ((struct rpl_dao_ack_t*)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN])); +} static struct rpl_dis_t* get_rpl_send_dis_buf(){ //return ((struct rpl_dis_t*)&(rpl_send_buffer[LLHDR_ICMPV6HDR_LEN])); return ((struct rpl_dis_t*)&(rpl_send_buffer[IPV6HDR_ICMPV6HDR_LEN])); @@ -94,9 +98,6 @@ static struct rpl_opt_transit_t* get_rpl_send_opt_transit_buf(uint8_t rpl_msg_le static struct ipv6_hdr_t * get_rpl_ipv6_buf(void){ return ((struct ipv6_hdr_t*)&(rpl_buffer[0])); } -//static struct icmpv6_hdr_t * get_rpl_icmpv6_buf(uint8_t ext_len){ -// return ((struct icmpv6_hdr_t*)&(rpl_buffer[IPV6_HDR_LEN + ext_len])); -//} static struct rpl_dio_t* get_rpl_dio_buf(){ return ((struct rpl_dio_t*)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN])); } @@ -104,9 +105,9 @@ static struct rpl_dio_t* get_rpl_dio_buf(){ static struct rpl_dao_t* get_rpl_dao_buf(){ return ((struct rpl_dao_t*)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN])); } -/*static struct rpl_dao_ack_t* get_rpl_dao_ack_buf(){ +static struct rpl_dao_ack_t* get_rpl_dao_ack_buf(){ return ((struct rpl_dao_ack_t*)&(buffer[LLHDR_ICMPV6HDR_LEN])); -}*/ +} static struct rpl_dis_t* get_rpl_dis_buf(){ return ((struct rpl_dis_t*)&(rpl_buffer[IPV6HDR_ICMPV6HDR_LEN])); } @@ -140,18 +141,13 @@ rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp){ return NULL; } -uint8_t rpl_init(transceiver_type_t trans, ipv6_addr_t *rpl_address){ +uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address){ vtimer_init(); mutex_init(&rpl_send_mutex); mutex_init(&rpl_recv_mutex); - if(rpl_address == NULL){ + if(rpl_address == 0){ return SIXLOWERROR_ADDRESS; } - //radio-address is 8-bit - if(rpl_address->uint8[14] != 0){ - return SIXLOWERROR_ADDRESS; - } - my_address = *rpl_address; //initialize routing table rpl_clear_routing_table(); init_trickle(); @@ -163,7 +159,11 @@ uint8_t rpl_init(transceiver_type_t trans, ipv6_addr_t *rpl_address){ objective_functions[0] = rpl_get_of0(); //objective_functions[1] = rpl_get_of_ETX() - sixlowpan_init(trans,rpl_address->uint8[15],0); + sixlowpan_init(trans,rpl_address,0); + //Wir benötigen einen Link Local prefix, um unsere entsprechende Addresse im Netz abzufragen + ipv6_addr_t ll_address; + ipv6_set_ll_prefix(&ll_address); + ipv6_get_saddr(&my_address, &ll_address); set_rpl_process_pid(rpl_process_pid); return SUCCESS; @@ -180,7 +180,7 @@ void rpl_init_root(){ } inst->id = RPL_DEFAULT_INSTANCE; inst->joined = 1; - + dodag = rpl_new_dodag(RPL_DEFAULT_INSTANCE, &my_address); if(dodag != NULL) { dodag->of = rpl_get_of_for_ocp(RPL_DEFAULT_OCP); @@ -193,7 +193,7 @@ void rpl_init_root(){ dodag->dio_redundancy = DEFAULT_DIO_REDUNDANCY_CONSTANT; dodag->maxrankincrease = 0; dodag->minhoprankincrease = (uint16_t)DEFAULT_MIN_HOP_RANK_INCREASE; - dodag->default_lifetime = (uint16_t)RPL_DEFAULT_LIFETIME; + dodag->default_lifetime = (uint8_t)RPL_DEFAULT_LIFETIME; dodag->lifetime_unit = RPL_LIFETIME_UNIT; dodag->version = RPL_COUNTER_INIT; dodag->grounded = RPL_GROUNDED; @@ -207,9 +207,6 @@ void rpl_init_root(){ } i_am_root = 1; start_trickle(dodag->dio_min, dodag->dio_interval_doubling, dodag->dio_redundancy); - //ipv6_addr_t mcast; - //ipv6_set_all_nds_mcast_addr(&mcast); - //send_DIO(&mcast); puts("ROOT INIT FINISHED"); } @@ -271,6 +268,7 @@ void send_DIO(ipv6_addr_t* destination){ } void send_DIS(ipv6_addr_t *destination){ + puts("Send DIS"); mutex_lock(&rpl_send_mutex); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); @@ -279,7 +277,7 @@ void send_DIS(ipv6_addr_t *destination){ icmp_send_buf->code = ICMP_CODE_DIO; icmp_send_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6); - rpl_dis_buf = get_rpl_dis_buf(); + rpl_send_dis_buf = get_rpl_send_dis_buf(); uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN; rpl_send(destination,(uint8_t*)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL); @@ -287,7 +285,7 @@ void send_DIS(ipv6_addr_t *destination){ } -void send_DAO(ipv6_addr_t *destination, uint8_t lifetime){ +void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime){ if(i_am_root){ return; } @@ -298,8 +296,10 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime){ if(destination == NULL){ destination = &my_dodag->my_preferred_parent->addr; } - printf("Sending DAO to\n"); - ipv6_print_addr(destination); + if(default_lifetime){ + lifetime=my_dodag->default_lifetime; + } + puts("sending DAO"); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); @@ -360,6 +360,34 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime){ mutex_unlock(&rpl_send_mutex, 0); } +void send_DAO_ACK(ipv6_addr_t *destination){ + puts("Send DAO_ACK to"); + ipv6_print_addr(destination); + rpl_dodag_t * my_dodag; + my_dodag = rpl_get_my_dodag(); + if(my_dodag == NULL){ + return; + } + mutex_lock(&rpl_send_mutex); + icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); + + icmp_send_buf->type = ICMP_RPL_CONTROL; + icmp_send_buf->code = ICMP_CODE_DAO_ACK; + icmp_send_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6); + + rpl_send_dao_ack_buf = get_rpl_send_dao_ack_buf(); + rpl_send_dao_ack_buf->rpl_instanceid = my_dodag->instance->id; + rpl_send_dao_ack_buf->d_reserved = 0; + rpl_send_dao_ack_buf->dao_sequence = my_dodag->dao_seq; + rpl_send_dao_ack_buf->status = 0; + + uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN; + rpl_send(destination,(uint8_t*)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL); + mutex_unlock(&rpl_send_mutex, 0); + + +} + void rpl_process(void){ msg_t m_recv; @@ -378,27 +406,24 @@ void rpl_process(void){ switch(*code) { case(ICMP_CODE_DIS):{ recv_rpl_dis(); - puts("unlock after dis recv"); mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); break; } case(ICMP_CODE_DIO):{ recv_rpl_dio(); - puts("unlock after dio recv"); mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); break; } case(ICMP_CODE_DAO):{ recv_rpl_dao(); - puts("unlock after dao recv"); mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); break; } case(ICMP_CODE_DAO_ACK):{ - puts("unlock after dao_ack recv"); + recv_rpl_dao_ack(); mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); break; @@ -660,7 +685,6 @@ void recv_rpl_dis(void){ } void recv_rpl_dao(void){ - printf("Receiving DAO\n"); rpl_dodag_t *my_dodag = rpl_get_my_dodag(); if(my_dodag == NULL){ printf("[Error] got DAO without beeing part of a Dodag\n"); @@ -701,7 +725,7 @@ void recv_rpl_dao(void){ len += rpl_opt_transit_buf->length +2; //Die eigentliche Lebenszeit einer Route errechnet sich aus (Lifetime aus DAO) * (Lifetime Unit) Sekunden rpl_add_routing_entry(&rpl_opt_target_buf->target, &ipv6_buf->srcaddr, rpl_opt_transit_buf->path_lifetime * my_dodag->lifetime_unit); - printf("new route added\n"); + puts("Updated route \n"); increment_seq = 1; break; } @@ -718,12 +742,30 @@ void recv_rpl_dao(void){ break; } } + send_DAO_ACK(&ipv6_buf->srcaddr); if(increment_seq){ RPL_COUNTER_INCREMENT(my_dodag->dao_seq); delay_dao(); } } +void recv_rpl_dao_ack(void){ + rpl_dodag_t *my_dodag = rpl_get_my_dodag(); + if(my_dodag == NULL){ + return; + } + rpl_dao_ack_buf = get_rpl_dao_ack_buf(); + if(rpl_dao_ack_buf->rpl_instanceid != my_dodag->instance->id){ + return; + } + if(rpl_dao_ack_buf->status != 0){ + return; + } + puts("Received DAO ACK"); + dao_ack_received(); + +} + void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_t next_header, void *tcp_socket){ uint8_t *p_ptr; ipv6_send_buf = get_rpl_send_ipv6_buf(); @@ -739,8 +781,6 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ memcpy(&(ipv6_send_buf->destaddr), destination, 16); ipv6_get_saddr(&(ipv6_send_buf->srcaddr), &(ipv6_send_buf->destaddr)); - //memcpy(&(ipv6_send_buf->srcaddr), &my_address, 16); - ipv6_print_addr(&ipv6_send_buf->srcaddr); //Wenn das Paket in der rpl.c "zusammegebaut" wurde, wurde dafür ohnehin der rpl_send_buf verwendet. //In diesem Fall muss also keine memcopy Aktion durchgeführt werden, da sich der payload bereits @@ -755,8 +795,6 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ lowpan_init((ieee_802154_long_t*)&(ipv6_send_buf->destaddr.uint16[4]),(uint8_t*)ipv6_send_buf); } else{ - puts("sending packet to"); - ipv6_print_addr(&ipv6_send_buf->destaddr); //find right next hop before sending ipv6_addr_t *next_hop = rpl_get_next_hop(&ipv6_send_buf->destaddr); if(next_hop == NULL){ @@ -789,10 +827,16 @@ ipv6_addr_t *rpl_get_next_hop(ipv6_addr_t * addr){ } void rpl_add_routing_entry(ipv6_addr_t *addr, ipv6_addr_t *next_hop, uint8_t lifetime){ + rpl_routing_entry_t * entry = rpl_find_routing_entry(addr); + if(entry != NULL){ + entry->lifetime = lifetime; + return; + } for(uint8_t i=0; imy_preferred_parent->addr, &best->addr)){ if(my_dodag->mop != NO_DOWNWARD_ROUTES){ //send DAO with ZERO_LIFETIME to old parent - send_DAO(&my_dodag->my_preferred_parent->addr, 0); + send_DAO(&my_dodag->my_preferred_parent->addr, 0, false); } my_dodag->my_preferred_parent = best; if(my_dodag->mop != NO_DOWNWARD_ROUTES){ diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index b576060b83..1298654fb1 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -70,6 +70,7 @@ #define DEFAULT_MIN_HOP_RANK_INCREASE 256 //DAO_DELAY is in seconds #define DEFAULT_DAO_DELAY 3 +#define DEFAULT_WAIT_FOR_DAO_ACK 10 #define RPL_DODAG_ID_LEN 16 //others diff --git a/sys/net/sixlowpan/rpl/trickle.c b/sys/net/sixlowpan/rpl/trickle.c index 38b6987f64..9a5667aa91 100644 --- a/sys/net/sixlowpan/rpl/trickle.c +++ b/sys/net/sixlowpan/rpl/trickle.c @@ -14,6 +14,8 @@ int interval_over_pid; int dao_delay_over_pid; int rt_timer_over_pid; +bool ack_received; + uint8_t k; uint32_t Imin; uint8_t Imax; @@ -48,9 +50,7 @@ void reset_trickletimer(void){ void init_trickle(void){ //Create threads -// timer_over_pid = thread_create(timer_over_buf, TRICKLE_TIMER_STACKSIZE, -// PRIORITY_MAIN-1,CREATE_SLEEPING, -// trickle_timer_over, "trickle_timer_over"); + ack_received = true; timer_over_pid = thread_create(timer_over_buf, TRICKLE_TIMER_STACKSIZE, PRIORITY_MAIN-1,CREATE_STACKTEST, trickle_timer_over, "trickle_timer_over"); @@ -135,6 +135,7 @@ void trickle_interval_over(void){ void delay_dao(void){ dao_time = timex_set(DEFAULT_DAO_DELAY,0); + ack_received = false; vtimer_remove(&dao_timer); vtimer_set_wakeup(&dao_timer, dao_time, dao_delay_over_pid); } @@ -142,10 +143,18 @@ void delay_dao(void){ void dao_delay_over(void){ while(1){ thread_sleep(); - send_DAO(NULL, false); + if(ack_received == false){ + send_DAO(NULL, 0, true); + dao_time = timex_set(DEFAULT_WAIT_FOR_DAO_ACK,0); + vtimer_set_wakeup(&dao_timer, dao_time, dao_delay_over_pid); + } } } +void dao_ack_received(){ + ack_received = true; +} + void rt_timer_over(void){ rpl_routing_entry_t * rt; while(1){ diff --git a/sys/net/sixlowpan/rpl/trickle.h b/sys/net/sixlowpan/rpl/trickle.h index cfa19b6c7c..637a97ee4e 100644 --- a/sys/net/sixlowpan/rpl/trickle.h +++ b/sys/net/sixlowpan/rpl/trickle.h @@ -17,4 +17,5 @@ void trickle_timer_over(void); void trickle_interval_over(void); void delay_dao(void); void dao_delay_over(void); +void dao_ack_received(void); void rt_timer_over(void); diff --git a/sys/net/sixlowpan/sixlowip.c b/sys/net/sixlowpan/sixlowip.c index 8151b3f609..2372f6cee0 100644 --- a/sys/net/sixlowpan/sixlowip.c +++ b/sys/net/sixlowpan/sixlowip.c @@ -86,38 +86,38 @@ void sixlowpan_send(ipv6_addr_t *addr, uint8_t *payload, uint16_t p_len, uint8_t int icmpv6_demultiplex(const struct icmpv6_hdr_t *hdr) { switch(hdr->type) { case(ICMP_RTR_SOL):{ - printf("INFO: packet type: icmp router solicitation\n"); + puts("INFO: packet type: icmp router solicitation"); /* processing router solicitation */ recv_rtr_sol(); /* init solicited router advertisment*/ break; } case(ICMP_RTR_ADV):{ - printf("INFO: packet type: icmp router advertisment\n"); + puts("INFO: packet type: icmp router advertisment"); /* processing router advertisment */ recv_rtr_adv(); /* init neighbor solicitation */ break; } case(ICMP_NBR_SOL):{ - printf("INFO: packet type: icmp neighbor solicitation\n"); + puts("INFO: packet type: icmp neighbor solicitation"); recv_nbr_sol(); break; } case(ICMP_NBR_ADV):{ - printf("INFO: packet type: icmp neighbor advertisment\n"); + puts("INFO: packet type: icmp neighbor advertisment"); recv_nbr_adv(); break; } case(ICMP_RPL_CONTROL):{ - printf("INFO: packet type: RPL message\n"); + puts("INFO: packet type: RPL message"); if(rpl_process_pid != 0){ msg_t m_send; m_send.content.ptr = (char*) &hdr->code; msg_send(&m_send, rpl_process_pid, 1); } else{ - printf("INFO: no RPL handler registered\n"); + puts("INFO: no RPL handler registered"); } break; } From f7368395ffdbe2b2e5970f0b091299291de2d53b Mon Sep 17 00:00:00 2001 From: Eric Engel Date: Tue, 27 Mar 2012 22:18:35 +0200 Subject: [PATCH 2/2] only 10 DAO trys and unrecognized options now directly lead to abort --- sys/net/sixlowpan/rpl/rpl.c | 7 +++---- sys/net/sixlowpan/rpl/trickle.c | 8 ++++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/sys/net/sixlowpan/rpl/rpl.c b/sys/net/sixlowpan/rpl/rpl.c index fb5013dcfa..54ffcc9f78 100644 --- a/sys/net/sixlowpan/rpl/rpl.c +++ b/sys/net/sixlowpan/rpl/rpl.c @@ -395,7 +395,6 @@ void rpl_process(void){ while(1){ msg_receive(&m_recv); - puts("Got a RPL Package"); uint8_t *code; code = ((uint8_t*)m_recv.content.ptr); //pakettypen unterscheiden @@ -533,7 +532,7 @@ void recv_rpl_dio(void){ } default: printf("[Error] Unsupported DIO option\n"); - break; + return; } } @@ -677,7 +676,7 @@ void recv_rpl_dis(void){ break; } default: - break; + return; } } send_DIO(&ipv6_buf->srcaddr); @@ -739,7 +738,7 @@ void recv_rpl_dao(void){ } default: - break; + return; } } send_DAO_ACK(&ipv6_buf->srcaddr); diff --git a/sys/net/sixlowpan/rpl/trickle.c b/sys/net/sixlowpan/rpl/trickle.c index 9a5667aa91..bdbab211be 100644 --- a/sys/net/sixlowpan/rpl/trickle.c +++ b/sys/net/sixlowpan/rpl/trickle.c @@ -15,6 +15,7 @@ int dao_delay_over_pid; int rt_timer_over_pid; bool ack_received; +uint8_t dao_counter; uint8_t k; uint32_t Imin; @@ -74,7 +75,7 @@ void start_trickle(uint8_t DIOIntMin, uint8_t DIOIntDoubl, uint8_t DIORedundancy Imax = DIOIntDoubl; //Eigentlich laut Spezifikation erste Bestimmung von I wie auskommentiert: //I = Imin + ( rand() % ( (Imin << Imax) - Imin + 1 ) ); - I = Imin + ( rand() % ( (4*Imin) - Imin + 1 ) ); + I = Imin + ( rand() % ( (4*Imin) - Imin + 1 ) ) ; t = (I/2) + ( rand() % ( I - (I/2) + 1 ) ); t_time = timex_set(0,t*1000); @@ -136,6 +137,7 @@ void trickle_interval_over(void){ void delay_dao(void){ dao_time = timex_set(DEFAULT_DAO_DELAY,0); ack_received = false; + dao_counter = 0; vtimer_remove(&dao_timer); vtimer_set_wakeup(&dao_timer, dao_time, dao_delay_over_pid); } @@ -143,7 +145,9 @@ void delay_dao(void){ void dao_delay_over(void){ while(1){ thread_sleep(); - if(ack_received == false){ + //10 DAOs will do... TODO: define + if((ack_received == false) && (dao_counter < 10)){ + dao_counter++; send_DAO(NULL, 0, true); dao_time = timex_set(DEFAULT_WAIT_FOR_DAO_ACK,0); vtimer_set_wakeup(&dao_timer, dao_time, dao_delay_over_pid);