diff --git a/sys/net/sixlowpan/rpl/rpl.c b/sys/net/sixlowpan/rpl/rpl.c index fef01554e0..01c6e5f9dc 100644 --- a/sys/net/sixlowpan/rpl/rpl.c +++ b/sys/net/sixlowpan/rpl/rpl.c @@ -12,12 +12,8 @@ #include "sys/net/sixlowpan/sixlowerror.h" char rpl_process_buf[RPL_PROCESS_STACKSIZE]; -//counters -uint8_t act_dodag_version = 240; -uint8_t dao_sequence = 240; -uint8_t path_sequence = 240; -//other global variables - +//global variables +char i_am_root = 0; rpl_of_t *objective_functions[NUMBER_IMPLEMENTED_OFS]; rpl_routing_entry_t routing_table[RPL_MAX_ROUTING_ENTRIES]; unsigned int rpl_process_pid; @@ -34,6 +30,8 @@ static struct rpl_dao_t *rpl_dao_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; +static struct rpl_opt_target_t * rpl_opt_target_buf; static struct rpl_dio_t* get_rpl_dio_buf(){ @@ -57,6 +55,14 @@ static struct rpl_opt_dodag_conf_t* get_rpl_opt_dodag_conf_buf(uint8_t rpl_msg_l return ((struct rpl_opt_dodag_conf_t*)&(buffer[LLHDR_ICMPV6HDR_LEN + rpl_msg_len])); } +static struct rpl_opt_solicited_t* get_rpl_opt_solicited_buf(uint8_t rpl_msg_len){ + return ((struct rpl_opt_solicited_t*)&(buffer[LLHDR_ICMPV6HDR_LEN + rpl_msg_len])); +} + +static struct rpl_opt_target_t* get_rpl_opt_target_buf(uint8_t rpl_msg_len){ + return ((struct rpl_opt_target_t*)&(buffer[LLHDR_ICMPV6HDR_LEN + rpl_msg_len])); +} + rpl_of_t *rpl_get_of_for_ocp(uint16_t ocp){ for(uint16_t i=0; i < NUMBER_IMPLEMENTED_OFS; i++){ if(ocp == objective_functions[i]->ocp){ @@ -118,7 +124,7 @@ void rpl_init_root(){ dodag->minhoprankincrease = (uint16_t)DEFAULT_MIN_HOP_RANK_INCREASE; dodag->default_lifetime = (uint16_t)RPL_DEFAULT_LIFETIME; dodag->lifetime_unit = RPL_LIFETIME_UNIT; - dodag->version = 0; + dodag->version = RPL_COUNTER_INIT; dodag->grounded = RPL_GROUNDED; dodag->my_rank = RPL_ROOT_RANK; dodag->joined = 1; @@ -128,7 +134,7 @@ void rpl_init_root(){ printf("Error - could not generate DODAG\n"); return; } - + i_am_root = 1; start_trickle(dodag->dio_min, dodag->dio_interval_doubling, dodag->dio_redundancy); } @@ -213,9 +219,23 @@ void send_DAO(){ //rpl_dao_buf->k_d_flags = 0x00; //TODO:dao_sequence handling rpl_dao_buf->dao_sequence = 0x00; + uint16_t opt_len = 0; + rpl_opt_target_buf = get_rpl_opt_target_buf(DAO_BASE_LEN); + //Alle Ziele aus der Routing Tabelle als Target eintragen + //TODO: Ausnahme default_route zu Parent + for(uint8_t i=0; itype=RPL_OPT_TARGET; + rpl_opt_target_buf->length=RPL_OPT_TARGET_LEN; + rpl_opt_target_buf->flags=0x00; + rpl_opt_target_buf->prefix_length=16; + memcpy(&rpl_opt_target_buf->target,&routing_table[i].address,sizeof(ipv6_addr_t)); + opt_len += RPL_OPT_TARGET_LEN +2; + rpl_opt_target_buf = get_rpl_opt_target_buf(DAO_BASE_LEN + opt_len); + } + } - - uint16_t plen = ICMPV6_HDR_LEN + DAO_BASE_LEN; + uint16_t plen = ICMPV6_HDR_LEN + DAO_BASE_LEN + opt_len; rpl_send(&my_dodag->my_preferred_parent->addr,(uint8_t*)icmp_buf, plen, PROTO_NUM_ICMPV6, NULL); } @@ -317,6 +337,7 @@ void recv_rpl_dio(void){ has_dodag_conf_opt = 1; if(rpl_opt_buf->length != RPL_OPT_DODAG_CONF_LEN){ //error malformed + return; } rpl_opt_dodag_conf_buf = get_rpl_opt_dodag_conf_buf(len); dio_dodag.dio_interval_doubling = rpl_opt_dodag_conf_buf->DIOIntDoubl; @@ -333,6 +354,7 @@ void recv_rpl_dio(void){ case(RPL_OPT_PREFIX_INFO):{ if(rpl_opt_buf->length != RPL_OPT_PREFIX_INFO_LEN){ //error malformed + return; } len += RPL_OPT_PREFIX_INFO_LEN +2; break; @@ -378,7 +400,7 @@ void recv_rpl_dio(void){ if( dio_dodag.version > my_dodag->version){ printf("New Version of dodag\n"); if(my_dodag->my_rank == ROOT_RANK){ - my_dodag->version = dio_dodag.version +1; + my_dodag->version = RPL_COUNTER_INCREMENT(dio_dodag.version); reset_trickletimer(); } else{ @@ -418,7 +440,54 @@ void recv_rpl_dio(void){ } void recv_rpl_dis(void){ - + rpl_dodag_t *my_dodag = rpl_get_my_dodag(); + if(my_dodag == NULL){ + return; + } + ipv6_buf = get_ipv6_buf(); + rpl_dis_buf = get_rpl_dis_buf(); + int len = DIS_BASE_LEN; + while(len < (ipv6_buf->length - ICMPV6_HDR_LEN) ){ + rpl_opt_buf = get_rpl_opt_buf(len); + switch(rpl_opt_buf->type){ + case(RPL_OPT_PAD1):{ + len += 1; + break; + } + case(RPL_OPT_PADN):{ + len += rpl_opt_buf->length +2; + break; + } + case(RPL_OPT_SOLICITED_INFO):{ + len+= RPL_OPT_SOLICITED_INFO_LEN+2; + //extract + check + if(rpl_opt_buf->length != RPL_OPT_SOLICITED_INFO_LEN){ + //error malformed + return; + } + rpl_opt_solicited_buf = get_rpl_opt_solicited_buf(len); + if(rpl_opt_solicited_buf->VID_Flags & RPL_DIS_I_MASK){ + if(my_dodag->instance->id != rpl_opt_solicited_buf->rplinstanceid){ + return; + } + } + if(rpl_opt_solicited_buf->VID_Flags & RPL_DIS_D_MASK){ + if(!rpl_equal_id(&my_dodag->dodag_id, &rpl_opt_solicited_buf->dodagid)){ + return; + } + } + if(rpl_opt_solicited_buf->VID_Flags & RPL_DIS_V_MASK){ + if(my_dodag->version != rpl_opt_solicited_buf->version){ + return; + } + } + break; + } + default: + break; + } + } + send_DIO(&ipv6_buf->srcaddr); } @@ -427,7 +496,7 @@ void recv_rpl_dao(void){ rpl_dao_buf = get_rpl_dao_buf(); int len = DAO_BASE_LEN; - while(len < (ipv6_buf->length - LLHDR_ICMPV6HDR_LEN) ){ + while(len < (ipv6_buf->length - ICMPV6_HDR_LEN) ){ rpl_opt_buf = get_rpl_opt_buf(len); switch(rpl_opt_buf->type){ @@ -503,9 +572,15 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ //find right next hop before sending ipv6_addr_t *next_hop = rpl_get_next_hop(&ipv6_buf->destaddr); if(next_hop == NULL){ - //oops... entweder bin ich root und weiß nicht wohin mit dem paket, oder es ist kein - //preferred parent eingetragen, was nicht passieren sollte. - printf("[Error] destination unknown\n"); + if(i_am_root){ + //oops... entweder bin ich root und weiß nicht wohin mit dem paket, oder es ist kein + //preferred parent eingetragen, was nicht passieren sollte. + printf("[Error] destination unknown\n"); + return; + } + else{ + next_hop = rpl_get_my_preferred_parent(); + } } lowpan_init((ieee_802154_long_t*)&(next_hop->uint16[4]),(uint8_t*)ipv6_buf); } @@ -518,10 +593,11 @@ ipv6_addr_t *rpl_get_next_hop(ipv6_addr_t * addr){ return &routing_table[i].next_hop; } } - return rpl_get_my_preferred_parent(); + return NULL; } void rpl_add_routing_entry(ipv6_addr_t *addr, ipv6_addr_t *next_hop){ + //TODO: if no free entry, delete worst parent for(uint8_t i=0; imy_preferred_parent->addr,address)){ + //set_new_preferred_parent + } for(int i=0;imin_rank = my_dodag->my_rank; start_trickle(my_dodag->dio_min, my_dodag->dio_interval_doubling, my_dodag->dio_redundancy); - //TODO: start sending DAOs - + delay_dao(); } void rpl_global_repair(rpl_dodag_t *dodag){ diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index 108c62b088..3c04c56bab 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -26,6 +26,8 @@ #define RPL_OPT_LEN 2 #define RPL_OPT_DODAG_CONF_LEN 14 #define RPL_OPT_PREFIX_INFO_LEN 30 +#define RPL_OPT_SOLICITED_INFO_LEN 19 +#define RPL_OPT_TARGET_LEN 18 //message options #define RPL_OPT_PAD1 0 @@ -64,6 +66,7 @@ #define DEFAULT_DIO_INTERVAL_DOUBLINGS 20 #define DEFAULT_DIO_REDUNDANCY_CONSTANT 10 #define DEFAULT_MIN_HOP_RANK_INCREASE 256 +//DAO_DELAY is in seconds #define DEFAULT_DAO_DELAY 1 //others @@ -80,6 +83,9 @@ #define RPL_PRF_MASK 0x7 #define RPL_MOP_SHIFT 3 #define RPL_SHIFTED_MOP_MASK 0x7 +#define RPL_DIS_V_MASK 0x80 +#define RPL_DIS_I_MASK 0x40 +#define RPL_DIS_D_MASK 0x20 #define RPL_GROUNDED_SHIFT 7 #define RPL_DEFAULT_OCP 0 @@ -137,6 +143,24 @@ typedef struct __attribute__((packed)) rpl_opt_dodag_conf_t { uint16_t lifetime_unit; } rpl_opt_dodag_conf_t; +typedef struct __attribute__((packed)) rpl_opt_solicited_t { + uint8_t type; + uint8_t length; + uint8_t rplinstanceid; + uint8_t VID_Flags; + ipv6_addr_t dodagid; + uint8_t version; +} rpl_opt_solicited_t; + +//ipv6_addr_t target may be replaced by a target prefix of variable length +typedef struct __attribute__((packed)) rpl_opt_target_t { + uint8_t type; + uint8_t length; + uint8_t flags; + uint8_t prefix_length; + ipv6_addr_t target; +} rpl_opt_target_t; + struct rpl_dodag_t; typedef struct rpl_parent_t { diff --git a/sys/net/sixlowpan/rpl/trickle.c b/sys/net/sixlowpan/rpl/trickle.c index 4efad84fa9..1119551a35 100644 --- a/sys/net/sixlowpan/rpl/trickle.c +++ b/sys/net/sixlowpan/rpl/trickle.c @@ -6,8 +6,10 @@ char timer_over_buf[TRICKLE_TIMER_STACKSIZE]; char interval_over_buf[TRICKLE_INTERVAL_STACKSIZE]; +char dao_delay_over_buf[DAO_DELAY_STACKSIZE]; int timer_over_pid; int interval_over_pid; +int dao_delay_over_pid; uint8_t k; uint32_t Imin; @@ -17,8 +19,10 @@ uint32_t t; uint16_t c; vtimer_t trickle_t_timer; vtimer_t trickle_I_timer; +vtimer_t dao_timer; timex_t t_time; timex_t I_time; +timex_t dao_time; //struct für trickle parameter?? void reset_trickletimer(void){ @@ -41,6 +45,9 @@ void init_trickle(void){ interval_over_pid = thread_create(interval_over_buf, TRICKLE_INTERVAL_STACKSIZE, PRIORITY_MAIN-1, CREATE_SLEEPING, trickle_interval_over, "trickle_interval_over"); + dao_delay_over_pid = thread_create(dao_delay_over_buf, DAO_DELAY_STACKSIZE, + PRIORITY_MAIN-1, CREATE_SLEEPING, + dao_delay_over, "dao_delay_over"); } @@ -96,3 +103,15 @@ void trickle_interval_over(void){ } } + +void delay_dao(void){ + dao_time = timex_set(DEFAULT_DAO_DELAY,0); + vtimer_set_wakeup(&dao_timer, dao_time, dao_delay_over_pid); +} + +void dao_delay_over(void){ + while(1){ + send_DAO(); + thread_sleep(); + } +} diff --git a/sys/net/sixlowpan/rpl/trickle.h b/sys/net/sixlowpan/rpl/trickle.h index b953b39be8..be4016fcfd 100644 --- a/sys/net/sixlowpan/rpl/trickle.h +++ b/sys/net/sixlowpan/rpl/trickle.h @@ -3,6 +3,7 @@ #define TRICKLE_TIMER_STACKSIZE 3072 #define TRICKLE_INTERVAL_STACKSIZE 3072 +#define DAO_DELAY_STACKSIZE 2048 void reset_trickletimer(void); void init_trickle(void); @@ -10,4 +11,5 @@ void start_trickle(uint8_t DIOINtMin, uint8_t DIOIntDoubl, uint8_t DIORedundancy void trickle_increment_counter(void); void trickle_timer_over(void); void trickle_interval_over(void); - +void delay_dao(void); +void dao_delay_over(void);