diff --git a/projects/test_rpl/Jamfile b/projects/test_rpl/Jamfile index 876f952b26..7e37eca2da 100644 --- a/projects/test_rpl/Jamfile +++ b/projects/test_rpl/Jamfile @@ -1,5 +1,5 @@ SubDir TOP projects test_rpl ; -Module test_rpl : main.c : auto_init vtimer 6lowpan uart0 posix_io cc110x_ng rpl ; +Module test_rpl : main.c : shell posix_io uart0 auto_init vtimer 6lowpan uart0 posix_io cc110x_ng rpl ; UseModule test_rpl ; diff --git a/projects/test_rpl/main.c b/projects/test_rpl/main.c index 188e85ef5d..1af3d548d5 100644 --- a/projects/test_rpl/main.c +++ b/projects/test_rpl/main.c @@ -2,25 +2,118 @@ #include #include #include + +#include +#include +#include + #include "sys/net/sixlowpan/sixlowip.h" #include "sys/net/sixlowpan/sixlowpan.h" #include "sys/net/sixlowpan/sixlowerror.h" #include "sys/net/sixlowpan/rpl/rpl.h" -int main(void) -{ - uint16_t root = 0x0002; - ipv6_addr_t std_addr; - uint16_t r_addr = root; +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); + + if(res < 1){ + printf("Usage: init address\n"); + printf("\tr\tinitialize as root\n"); + printf("\tn\tinitialize as node router\n"); + 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 = rpl_init(TRANSCEIVER_CC1100, &std_addr); - if(state != SUCCESS){ - printf("Error initializing RPL\n"); - } - if(root == 0x0001){ - rpl_init_root(); - } - printf("RPL INIT FINISHED\n"); - while(1); + uint8_t state; + switch (command) { + case 'r': + printf("INFO: Initialize as root on address \n"); + ipv6_print_addr(&std_addr); + if (r_addr > 255) { + printf("ERROR: address not an 8 bit integer\n"); + return; + } + state = rpl_init(TRANSCEIVER_CC1100, &std_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); + if (r_addr > 255) { + printf("ERROR: address not an 8 bit integer\n"); + return; + } + state = rpl_init(TRANSCEIVER_CC1100, &std_addr); + if(state != SUCCESS){ + printf("Error initializing RPL\n"); + } + break; + default: + printf("ERROR: Unknown command '%c'\n", command); + break; + } +} + +void table(char *str){ + rpl_routing_entry_t * rtable; + rtable = rpl_get_routing_table(); + printf("---------------------------\n"); + printf("OUTPUT\n"); + printf("---------------------------\n"); + for(int i=0;itype = ICMP_RPL_CONTROL; icmp_buf->code = ICMP_CODE_DIO; + icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6); rpl_dio_buf = get_rpl_dio_buf(); memset(rpl_dio_buf, 0, sizeof(*rpl_dio_buf)); @@ -163,8 +165,8 @@ void send_DIO(ipv6_addr_t* destination){ rpl_dio_buf->flags = 0; rpl_dio_buf->reserved = 0; rpl_dio_buf->dodagid = mydodag->dodag_id; - printf("Send DIO with DODAGID: \n"); - ipv6_print_addr(&rpl_dio_buf->dodagid); + //printf("Send DIO with DODAGID: \n"); + //ipv6_print_addr(&rpl_dio_buf->dodagid); int opt_hdr_len = 0; //DODAG Configuration Option! @@ -195,7 +197,9 @@ void send_DIS(ipv6_addr_t *destination){ icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmp_buf->type = ICMP_RPL_CONTROL; - icmp_buf->code = ICMP_CODE_DIO; + icmp_buf->code = ICMP_CODE_DIO; + icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6); + rpl_dis_buf = get_rpl_dis_buf(); uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN; @@ -203,10 +207,14 @@ void send_DIS(ipv6_addr_t *destination){ } void send_DAO(){ + if(i_am_root){ + return; + } icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); icmp_buf->type = ICMP_RPL_CONTROL; icmp_buf->code = ICMP_CODE_DAO; + icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6); rpl_dodag_t * my_dodag; my_dodag = rpl_get_my_dodag(); @@ -217,25 +225,32 @@ void send_DAO(){ memset(rpl_dao_buf,0,sizeof(*rpl_dao_buf)); rpl_dao_buf->rpl_instanceid = my_dodag->instance->id; //rpl_dao_buf->k_d_flags = 0x00; - //TODO:dao_sequence handling - rpl_dao_buf->dao_sequence = 0x00; + rpl_dao_buf->dao_sequence = my_dodag->dao_seq; 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; + rpl_opt_target_buf->prefix_length= RPL_DODAG_ID_LEN; 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); } } + //Add own address + rpl_opt_target_buf->type=RPL_OPT_TARGET; + rpl_opt_target_buf->length=RPL_OPT_TARGET_LEN; + rpl_opt_target_buf->flags=0x00; + rpl_opt_target_buf->prefix_length= RPL_DODAG_ID_LEN; + memcpy(&rpl_opt_target_buf->target,&my_address,sizeof(ipv6_addr_t)); + printf("Sending DAO with length %d\n",rpl_opt_target_buf->prefix_length); + opt_len += RPL_OPT_TARGET_LEN +2; uint16_t plen = ICMPV6_HDR_LEN + DAO_BASE_LEN + opt_len; + printf("Sending DAO\n"); rpl_send(&my_dodag->my_preferred_parent->addr,(uint8_t*)icmp_buf, plen, PROTO_NUM_ICMPV6, NULL); } @@ -397,9 +412,11 @@ void recv_rpl_dio(void){ if(rpl_equal_id(&my_dodag->dodag_id, &dio_dodag.dodag_id)){ //Mein DODAG - if( dio_dodag.version > my_dodag->version){ + if(RPL_COUNTER_GREATER_THAN(dio_dodag.version,my_dodag->version) ){ printf("New Version of dodag\n"); if(my_dodag->my_rank == ROOT_RANK){ + //Jemand hat ein DIO mit einer höheren Version als der richtigen gesendet + //Wir erhöhen diese Version noch einmal, und machen sie zur neuen my_dodag->version = RPL_COUNTER_INCREMENT(dio_dodag.version); reset_trickletimer(); } @@ -408,7 +425,8 @@ void recv_rpl_dio(void){ } return; } - else if( dio_dodag.version < my_dodag->version){ + else if( RPL_COUNTER_GREATER_THAN(my_dodag->version, dio_dodag.version) ){ + //ein Knoten hat noch eine kleinere Versionsnummer -> mehr DIOs senden reset_trickletimer(); return; } @@ -427,6 +445,7 @@ void recv_rpl_dio(void){ parent = rpl_find_parent(&ipv6_buf->srcaddr); if(parent == NULL){ //neuen Elternknoten hinzufuegen + //TODO: Checken, ob der Knoten parent sein darf parent = rpl_new_parent(&dio_dodag, &ipv6_buf->srcaddr, rpl_dio_buf->rank); if(parent == NULL){ return; @@ -492,10 +511,16 @@ 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"); + return; + } ipv6_buf = get_ipv6_buf(); - rpl_dao_buf = get_rpl_dao_buf(); int len = DAO_BASE_LEN; + uint8_t increment_seq = 0; while(len < (ipv6_buf->length - ICMPV6_HDR_LEN) ){ rpl_opt_buf = get_rpl_opt_buf(len); switch(rpl_opt_buf->type){ @@ -513,6 +538,12 @@ void recv_rpl_dao(void){ break; } case(RPL_OPT_TARGET):{ + rpl_opt_target_buf = get_rpl_opt_target_buf(len); + if(rpl_opt_target_buf->prefix_length != RPL_DODAG_ID_LEN){ + printf("prefixes are not supported yet"); + } + rpl_add_routing_entry(&rpl_opt_target_buf->target, &ipv6_buf->srcaddr); + increment_seq = 1; len += rpl_opt_buf->length +2; break; } @@ -529,6 +560,10 @@ void recv_rpl_dao(void){ break; } } + if(increment_seq){ + RPL_COUNTER_INCREMENT(my_dodag->dao_seq); + delay_dao(); + } } void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_t next_header, void *tcp_socket){ @@ -573,13 +608,17 @@ void rpl_send(ipv6_addr_t *destination, uint8_t *payload, uint16_t p_len, uint8_ ipv6_addr_t *next_hop = rpl_get_next_hop(&ipv6_buf->destaddr); if(next_hop == NULL){ 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. + //oops... ich bin root und weiß nicht wohin mit dem paketn printf("[Error] destination unknown\n"); return; } else{ next_hop = rpl_get_my_preferred_parent(); + if(next_hop == NULL){ + //kein preferred parent eingetragen, was nicht passieren sollte. + printf("[Error] no preferred parent\n"); + return; + } } } lowpan_init((ieee_802154_long_t*)&(next_hop->uint16[4]),(uint8_t*)ipv6_buf); @@ -597,11 +636,12 @@ 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){ - //TODO: if no free entry, delete worst parent for(uint8_t i=0; ijoined = 0; dodag->my_preferred_parent = NULL; - //TODO: parents aus Liste löschen? + //parents aus Liste löschen + rpl_delete_all_parents(); + //TODO: Poison mit INFINITE_RANK } bool rpl_equal_id(ipv6_addr_t *id1, ipv6_addr_t *id2){ @@ -97,6 +99,7 @@ bool rpl_equal_id(ipv6_addr_t *id1, ipv6_addr_t *id2){ } } return true; + } rpl_parent_t *rpl_new_parent(rpl_dodag_t *dodag, ipv6_addr_t *address, uint16_t rank){ @@ -113,7 +116,8 @@ rpl_parent_t *rpl_new_parent(rpl_dodag_t *dodag, ipv6_addr_t *address, uint16_t return parent; } } - return NULL; + rpl_delete_worst_parent(); + return rpl_new_parent(dodag, address, rank); } rpl_parent_t *rpl_find_parent(ipv6_addr_t *address){ @@ -128,23 +132,55 @@ rpl_parent_t *rpl_find_parent(ipv6_addr_t *address){ return NULL; } -void rpl_delete_parent(ipv6_addr_t * address){ +void rpl_delete_parent(rpl_parent_t * parent){ rpl_dodag_t * my_dodag = rpl_get_my_dodag(); - //TODO:check if this was the preferred parent, find new parent, if it was last parent leave dodag - if(rpl_equal_id(&my_dodag->my_preferred_parent->addr,address)){ - //set_new_preferred_parent + //check if this was the preferred parent, find new parent, if it was last parent leave dodag + char new_preferred_parent = 0; + if( (my_dodag != NULL) && rpl_equal_id(&my_dodag->my_preferred_parent->addr, &parent->addr) ){ + new_preferred_parent = 1; + memset(parent,0,sizeof(*parent)); } - for(int i=0;i leave dodag; + //TODO: Erst nach Ablauf eines Timers verlassen, siehe RPL draft 8.2.2.1 DODAG Version + rpl_leave_dodag(my_dodag); + } + my_dodag->my_preferred_parent = &parents[best]; } } -void rpl_delete_parents_for_dodag(ipv6_addr_t * dodag_id){ +void rpl_delete_worst_parent(void){ + uint8_t worst = 0xFF; + uint16_t max_rank = 0x0000; + for(int i=0;i max_rank){ + worst = i; + max_rank = parents[i].rank; + } + } + if(worst == 0xFF){ + //Fehler, keine parents -> sollte nicht passieren + return; + } + rpl_delete_parent(&parents[worst]); } +void rpl_delete_all_parents(void){ + for(int i=0;ijoined = 1; my_dodag->my_preferred_parent = preferred_parent; my_dodag->my_rank = dodag->of->calc_rank(preferred_parent, dodag->my_rank); + my_dodag->dao_seq = RPL_COUNTER_INIT; my_dodag->min_rank = my_dodag->my_rank; start_trickle(my_dodag->dio_min, my_dodag->dio_interval_doubling, my_dodag->dio_redundancy); @@ -186,6 +223,7 @@ void rpl_global_repair(rpl_dodag_t *dodag){ printf("Error - no global repair possible, if not part of a DODAG\n"); return; } + //TODO: nachschauen - soll das wirklich so überschrieben werden? my_dodag->version = dodag->version; my_dodag->dtsn = dodag->dtsn; } diff --git a/sys/net/sixlowpan/rpl/rpl_dodag.h b/sys/net/sixlowpan/rpl/rpl_dodag.h index b6339db722..7688b69fb8 100644 --- a/sys/net/sixlowpan/rpl/rpl_dodag.h +++ b/sys/net/sixlowpan/rpl/rpl_dodag.h @@ -15,3 +15,6 @@ void rpl_leave_dodag(rpl_dodag_t * dodag); bool rpl_equal_id(ipv6_addr_t *id1, ipv6_addr_t *id2); void rpl_global_repair(rpl_dodag_t *dodag); ipv6_addr_t *rpl_get_my_preferred_parent(); +void rpl_delete_parent(rpl_parent_t *parent); +void rpl_delete_worst_parent(void); +void rpl_delete_all_parents(void); diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index 3c04c56bab..b4d19abee1 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -68,6 +68,7 @@ #define DEFAULT_MIN_HOP_RANK_INCREASE 256 //DAO_DELAY is in seconds #define DEFAULT_DAO_DELAY 1 +#define RPL_DODAG_ID_LEN 16 //others @@ -197,6 +198,7 @@ typedef struct rpl_dodag_t { uint8_t version; uint8_t grounded; uint16_t my_rank; + uint8_t dao_seq; uint16_t min_rank; uint8_t joined; rpl_parent_t *my_preferred_parent;