rpl nearly finished, rpl_test now with shell

This commit is contained in:
Eric Engel 2012-02-22 00:50:40 +01:00
parent 8124389151
commit f69fbfd686
7 changed files with 220 additions and 38 deletions

View File

@ -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 ;

View File

@ -2,25 +2,118 @@
#include <string.h>
#include <vtimer.h>
#include <thread.h>
#include <posix_io.h>
#include <shell.h>
#include <board_uart0.h>
#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;i<RPL_MAX_ROUTING_ENTRIES;i++){
if(rtable[i].used){
ipv6_print_addr(&rtable[i].address);
printf("--------------\n");
}
}
}
const shell_command_t shell_commands[] = {
{"init", "", init},
{"table", "", table},
{NULL, NULL, NULL}
};
int main(void) {
printf("RPL Test Application\n");
vtimer_init();
posix_open(uart0_handler_pid, 0);
shell_t shell;
shell_init(&shell, shell_commands, uart0_readc, uart0_putc);
shell_run(&shell);
return 0;
}
int old_main(void)
{
timex_t mytime = timex_set(10,0);
while(1){
rpl_routing_entry_t * rtable;
rtable = rpl_get_routing_table();
printf("---------------------------\n");
printf("OUTPUT\n");
printf("---------------------------\n");
for(int i=0;i<RPL_MAX_ROUTING_ENTRIES;i++){
if(rtable[i].used){
ipv6_print_addr(&rtable[i].address);
printf("--------------\n");
}
}
vtimer_sleep(mytime);
};
}

View File

@ -9,6 +9,7 @@
#include "sys/net/sixlowpan/sixlowmac.h"
#include "sys/net/sixlowpan/sixlowip.h"
#include "sys/net/sixlowpan/sixlowpan.h"
#include "sys/net/sixlowpan/sixlownd.h"
#include "sys/net/sixlowpan/sixlowerror.h"
char rpl_process_buf[RPL_PROCESS_STACKSIZE];
@ -152,6 +153,7 @@ void send_DIO(ipv6_addr_t* destination){
icmp_buf->type = 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; i<RPL_MAX_ROUTING_ENTRIES;i++){
if(routing_table[i].used){
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=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; i<RPL_MAX_ROUTING_ENTRIES; i++){
if(!routing_table[i].used){
routing_table[i].address = *addr;
routing_table[i].next_hop = *next_hop;
routing_table[i].used = 1;
break;
}
}
}
@ -621,3 +661,8 @@ void rpl_clear_routing_table(){
}
}
//This function is for debug output purpose only...
rpl_routing_entry_t *rpl_get_routing_table(void){
return routing_table;
}

View File

@ -24,3 +24,4 @@ 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);
void rpl_del_routing_entry(ipv6_addr_t *addr);
void rpl_clear_routing_table();
rpl_routing_entry_t *rpl_get_routing_table(void);

View File

@ -87,7 +87,9 @@ void rpl_del_dodag(rpl_dodag_t *dodag){
void rpl_leave_dodag(rpl_dodag_t * dodag){
dodag->joined = 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<RPL_MAX_PARENTS;i++){
if( parents[i].used && (rpl_equal_id(address, &parents[i].addr)) ){
memset(&parents[i], 0, sizeof(parents[i]));
uint8_t best = 0xFF;
uint16_t min_rank = 0xFFFF;
if(new_preferred_parent){
for(int i=0;i<RPL_MAX_PARENTS;i++){
if(parents[i].rank < min_rank){
best = i;
min_rank = parents[i].rank;
}
}
if(best == 0xFF){
//we have no more parents for this dodag -> 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<RPL_MAX_PARENTS;i++){
if(parents[i].rank > 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;i<RPL_MAX_PARENTS;i++){
memset(&parents[i],0,sizeof(parents[i]));
}
}
void rpl_join_dodag(rpl_dodag_t *dodag, ipv6_addr_t *parent, uint16_t parent_rank){
rpl_dodag_t *my_dodag;
rpl_parent_t *preferred_parent;
@ -174,6 +210,7 @@ void rpl_join_dodag(rpl_dodag_t *dodag, ipv6_addr_t *parent, uint16_t parent_ran
my_dodag->joined = 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;
}

View File

@ -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);

View File

@ -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;