From 812dafde773b1273095eaf421d98a34ca0e77f29 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Mon, 26 Nov 2012 17:03:08 +0100 Subject: [PATCH 01/35] deleted unused 'old_main' function --- projects/test_rpl/main.c | 23 ----------------------- sys/net/sixlowpan/rpl/of0.c | 1 + 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/projects/test_rpl/main.c b/projects/test_rpl/main.c index ea2b321526..adbb809d05 100644 --- a/projects/test_rpl/main.c +++ b/projects/test_rpl/main.c @@ -199,26 +199,3 @@ int main(void) { 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 Date: Tue, 4 Dec 2012 16:17:36 +0100 Subject: [PATCH 02/35] Basic files and functionstructure for a pingtest application created --- projects/test_ping/Jamfile | 5 +++ projects/test_ping/main.c | 62 ++++++++++++++++++++++++++++ projects/test_ping/tests/hello-world | 13 ++++++ 3 files changed, 80 insertions(+) create mode 100644 projects/test_ping/Jamfile create mode 100644 projects/test_ping/main.c create mode 100755 projects/test_ping/tests/hello-world diff --git a/projects/test_ping/Jamfile b/projects/test_ping/Jamfile new file mode 100644 index 0000000000..2470940cff --- /dev/null +++ b/projects/test_ping/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_ping ; + +Module test_ping : main.c ; + +UseModule test_ping ; diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c new file mode 100644 index 0000000000..c65fd0491e --- /dev/null +++ b/projects/test_ping/main.c @@ -0,0 +1,62 @@ +#include + +// Shell commands for this application +const shell_command_t shell_commands[] = { + {"help", "Prints a list of commands", help}, + {"init", "Initializes this node for a pingtest.", init}, + {"ping", "Makes this node a pinging node", ping}, + {"stop", "Stops the current node's ping-action and prints a summary", ping}, + {NULL, NULL, NULL} +}; + +/** + * Initializes this node with a given radio address and on a given channel or + * on a default channel, if no channel is given. A radio address must be given + * in any case. + */ +void init(char* arg) { +//TODO implement +} + +/** + * Prints the shellcommands that are usable in this application for reference. + */ +void help(char* unused) { +//TODO implement +} + +/** + * Sends out pings from this node to another node in a continuous manner, until + * the stop command is used. + */ +void ping(char* unused) { +//TODO implement +} + +/** + * Stops any current pinging-action by this node and prints a summary of how + * many pings got returned. + * If the node was not pinging at the time of the method-call, this method does + * nothing. + */ +void stop(char* unused) { +//TODO implement +} + +/** + * The main function for this application, starts the shell and waits for + * commands. + */ +int main(void) { + puts("Ping Test Application\n"); + puts("For commands type 'help'!\n"); + + shell_t shell; + shell_init(&shell, shell_commands, uart0_readc, uart0_putc); + + shell_run(&shell); + + return 0; + while (1) + ; +} diff --git a/projects/test_ping/tests/hello-world b/projects/test_ping/tests/hello-world new file mode 100755 index 0000000000..acde8265fe --- /dev/null +++ b/projects/test_ping/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + From fe7f3715952a9d674327697e7226e1925de85f11 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 4 Dec 2012 16:18:23 +0100 Subject: [PATCH 03/35] deleted wrong code --- projects/test_ping/main.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index c65fd0491e..eba917d396 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -57,6 +57,4 @@ int main(void) { shell_run(&shell); return 0; - while (1) - ; } From 2f912f2b3fe9397c2b1bf47dc4cd5721de2ec6a0 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 4 Dec 2012 17:17:50 +0100 Subject: [PATCH 04/35] basic function layout added --- projects/test_ping/Jamfile | 2 +- projects/test_ping/main.c | 48 +++++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/projects/test_ping/Jamfile b/projects/test_ping/Jamfile index 2470940cff..2e9663fa3c 100644 --- a/projects/test_ping/Jamfile +++ b/projects/test_ping/Jamfile @@ -1,5 +1,5 @@ SubDir TOP projects test_ping ; -Module test_ping : main.c ; +Module test_ping : main.c : shell shell_commands uart0 posix_io auto_init vtimer cc110x ; UseModule test_ping ; diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index eba917d396..0567ac3167 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -1,12 +1,26 @@ #include +#include +#include +#include + +#include +#include +#include +#include + +// Prototypes +void help(char * arg); +void init(char * arg); +void ping(char * arg); +void stop(char * arg); // Shell commands for this application -const shell_command_t shell_commands[] = { - {"help", "Prints a list of commands", help}, - {"init", "Initializes this node for a pingtest.", init}, - {"ping", "Makes this node a pinging node", ping}, - {"stop", "Stops the current node's ping-action and prints a summary", ping}, - {NULL, NULL, NULL} +const shell_command_t shell_commands[] = +{ { "help", "Prints the help", help }, + { "init", "Initializes this node with an address and a channel.", init }, + { "ping", "Makes this node a pinging node", ping }, + { "stop", "Stops the current node's pings and prints a summary", stop }, + { NULL, NULL, NULL } }; /** @@ -22,7 +36,13 @@ void init(char* arg) { * Prints the shellcommands that are usable in this application for reference. */ void help(char* unused) { -//TODO implement + printf("These are the usable commands:\n"); + printf("\thelp (commandname)\n"); + printf("\tinit [address] (channel)\n"); + printf("\tping [address] (time)\n"); + printf("\tstop\n"); + printf("\n"); + printf("[] = mandatory, () = optional"); } /** @@ -48,13 +68,15 @@ void stop(char* unused) { * commands. */ int main(void) { - puts("Ping Test Application\n"); - puts("For commands type 'help'!\n"); + puts("Ping Test Application\n"); + puts("For commands type 'help'!\n"); - shell_t shell; - shell_init(&shell, shell_commands, uart0_readc, uart0_putc); + posix_open(uart0_handler_pid, 0); - shell_run(&shell); + shell_t shell; + shell_init(&shell, shell_commands, uart0_readc, uart0_putc); - return 0; + shell_run(&shell); + + return 0; } From dd3ba2bfe3ae55ea192639dc1bbb6513dd321f51 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 4 Dec 2012 17:31:59 +0100 Subject: [PATCH 05/35] it is now a minimal functional project --- projects/test_ping/Jamfile | 2 +- projects/test_ping/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/test_ping/Jamfile b/projects/test_ping/Jamfile index 2e9663fa3c..ce99c97eee 100644 --- a/projects/test_ping/Jamfile +++ b/projects/test_ping/Jamfile @@ -1,5 +1,5 @@ SubDir TOP projects test_ping ; -Module test_ping : main.c : shell shell_commands uart0 posix_io auto_init vtimer cc110x ; +Module test_ping : main.c : shell shell_commands ps uart0 posix_io auto_init vtimer cc110x ; UseModule test_ping ; diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index 0567ac3167..a3d5eac1c8 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -42,7 +42,7 @@ void help(char* unused) { printf("\tping [address] (time)\n"); printf("\tstop\n"); printf("\n"); - printf("[] = mandatory, () = optional"); + printf("[] = mandatory, () = optional\n"); } /** From aed72abf4eb6e35f46205ef01266d8c346199ca6 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Sun, 9 Dec 2012 18:02:06 +0100 Subject: [PATCH 06/35] trying to get radio init to work --- projects/test_ping/Jamfile | 2 +- projects/test_ping/main.c | 188 +++++++++++++++++++++++++++++-------- projects/test_ping/main.h | 45 +++++++++ 3 files changed, 193 insertions(+), 42 deletions(-) create mode 100644 projects/test_ping/main.h diff --git a/projects/test_ping/Jamfile b/projects/test_ping/Jamfile index ce99c97eee..39a205aa69 100644 --- a/projects/test_ping/Jamfile +++ b/projects/test_ping/Jamfile @@ -1,5 +1,5 @@ SubDir TOP projects test_ping ; -Module test_ping : main.c : shell shell_commands ps uart0 posix_io auto_init vtimer cc110x ; +Module test_ping : main.c : shell shell_commands ps uart0 posix_io auto_init vtimer 6lowpan cc110x transceiver ; UseModule test_ping ; diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index a3d5eac1c8..2039089d4e 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -7,60 +9,161 @@ #include #include #include +#include -// Prototypes -void help(char * arg); -void init(char * arg); -void ping(char * arg); -void stop(char * arg); +#define STACKSIZE KERNEL_CONF_STACKSIZE_DEFAULT + +char stack[STACKSIZE]; // Shell commands for this application const shell_command_t shell_commands[] = -{ { "help", "Prints the help", help }, - { "init", "Initializes this node with an address and a channel.", init }, - { "ping", "Makes this node a pinging node", ping }, - { "stop", "Stops the current node's pings and prints a summary", stop }, - { NULL, NULL, NULL } -}; + { { "help", "Prints the help", help }, + { "init", + "Initializes this node with an address and a channel.", + init }, + { "ping", "Makes this node a pinging node", ping }, + { "stop", "Stops the current node's pings and prints a summary", + stop }, + { NULL, NULL, NULL } + }; -/** - * Initializes this node with a given radio address and on a given channel or - * on a default channel, if no channel is given. A radio address must be given - * in any case. - */ +// pid of ongoing ping thread, 0 if not set +int pid_pingthread = 0; + +// see header for documentation void init(char* arg) { -//TODO implement + transceiver_command_t tcmd; + msg_t m; + uint16_t addr = 0; + uint16_t chan = 10; + + printf("transceiver pid is %d.\n", transceiver_pid); + + int res = sscanf(arg, "init %hu %hu", &addr, &chan); + if (res == 1) { + puts("Setting address, keeping default channel"); + + if (addr >= MIN_ADDR && addr <= MAX_ADDR + && chan >= MIN_CHAN && chan <= MAX_CHAN) { + //addr. given, channel should be default, which is 10 for us + //check for validity in any case, just to be sure + + + puts("Initializing 6lowpan.."); + sixlowpan_init(TRANSCEIVER_CC1100,addr,0); + puts("Address set, setting channel"); + + tcmd.data = &chan; + m.type = SET_CHANNEL; + m.content.ptr = (void*) &tcmd; + + puts("waiting for transceiver.."); + msg_send_receive(&m, &m, transceiver_pid); + puts("Channel set."); + + } else { + printf("ERROR: The address for the node has to be in %d to %d.\n", + MIN_ADDR, MAX_ADDR); + } + + } else if (res == 2) { + puts("Setting address and channel"); + + if (addr >= MIN_ADDR && addr <= MAX_ADDR + && chan >= MIN_CHAN && chan <= MAX_CHAN) { + //addr. & channel are given, check validity + + puts("Initializing 6lowpan.."); + sixlowpan_init(TRANSCEIVER_CC1100,addr,0); + puts("address set, setting channel"); + + tcmd.data = &chan; + m.type = SET_CHANNEL; + m.content.ptr = (void*) &tcmd; + + puts("waiting for transceiver.."); + msg_send_receive(&m, &m, transceiver_pid); + puts("channel set"); + } else { + printf("ERROR: The address for the node has to be in %d to %d.\n", + MIN_ADDR, MAX_ADDR); + printf("ERROR: The channel for the node has to be in %d to %d.\n", + MIN_CHAN, MAX_CHAN); + } + //addr and channel given + } else { + //no correct argument given, but radio address is mandatory + puts("Usage: init [radioaddr] (radiochannel)"); + puts("Use 'help init' for more information on this command."); + } } -/** - * Prints the shellcommands that are usable in this application for reference. - */ -void help(char* unused) { - printf("These are the usable commands:\n"); - printf("\thelp (commandname)\n"); - printf("\tinit [address] (channel)\n"); - printf("\tping [address] (time)\n"); - printf("\tstop\n"); - printf("\n"); - printf("[] = mandatory, () = optional\n"); +// see header for documentation +void help(char* cmdname) { + char *command = cmdname; + while (*command != '\0' && *command++ != ' ') + ; //Skip the command by going till first space + + if (strlen(cmdname) == 4) { + puts("These are the usable commands:"); + puts("\thelp (commandname)"); + puts("\tinit [address] (channel)"); + puts("\tping [address] (time)"); + puts("\tstop"); + puts(""); + puts("[] = mandatory, () = optional"); + } else if (!strcasecmp("init", command)) { + puts("init: Initializes a node for radio communication."); + puts(" +"); + puts( + " +---[address]: The radio-address that this node should assume (range: 0 to 255)"); + puts(" + This argument is mandatory."); + puts(" +"); + puts(" +---(channel): The radio-channel that this node should use"); + puts(" This argument is optional."); + puts(" Uses a default channel if not given."); + } else if (!strcasecmp("ping", command)) { + puts( + "ping: Sends ping-messages to another node and records statistics on the number"); + puts( + " + of sent messages/received messages as well as the RTT of those pings."); + puts(" +"); + puts( + " +---[address]: The radio-address that this node should send its pings to)"); + puts(" + This argument is mandatory."); + puts(" +"); + puts( + " +---(time) : The duration (in seconds) that these ping messages should "); + puts(" be sent over"); + puts(" This argument is optional."); + puts(" Sends infinite pings when no time is given."); + } else if (!strcasecmp("stop", command)) { + puts("stop: Stops any ongoing pings this node sends out."); + puts( + " If this node is currently not sending any pings, this command does nothing."); + } else { + puts("The command given was not recognized. You gave:"); + puts(command); + puts("Recognized commands are 'init','ping' and 'stop'"); + } } -/** - * Sends out pings from this node to another node in a continuous manner, until - * the stop command is used. - */ -void ping(char* unused) { -//TODO implement +// see header for docs +void ping() { + //TODO implement } -/** - * Stops any current pinging-action by this node and prints a summary of how - * many pings got returned. - * If the node was not pinging at the time of the method-call, this method does - * nothing. - */ void stop(char* unused) { -//TODO implement + //TODO implement + if (pid_pingthread) { + } +} + +void hellothread(){ + while(true){ + puts("Hello!"); + vtimer_usleep(1000*2000); //2secs + } } /** @@ -71,6 +174,8 @@ int main(void) { puts("Ping Test Application\n"); puts("For commands type 'help'!\n"); + thread_create(stack, STACKSIZE, PRIORITY_MAIN -3,8, hellothread,"hello"); + posix_open(uart0_handler_pid, 0); shell_t shell; @@ -80,3 +185,4 @@ int main(void) { return 0; } + diff --git a/projects/test_ping/main.h b/projects/test_ping/main.h new file mode 100644 index 0000000000..6128b97e16 --- /dev/null +++ b/projects/test_ping/main.h @@ -0,0 +1,45 @@ +#ifndef PING_TEST_H + +#define PING_TEST_H + +#define MIN_ADDR 1 +#define MIN_CHAN MIN_ADDR +#define MAX_CHAN 14 +#define MAX_ADDR 255 + +/** + * @brief Shows a helping text. + * @param command the command name for which the help should be showed. + */ +void help(char * commandname); + +/** + * @brief Initializes a node for radio communication + * + * Initializes this node with a given radio address and on a given channel or + * on a default channel, if no channel is given. A radio address must be given + * in any case. + * + * @param arg + */ +void init(char * arg); + +/** + * @brief Pings another node. + * + * Sends out pings from this node to another node in a continuous manner, until + * the stop command is used. + */ +void ping(); + +/** + * Stops any current pinging-action by this node and prints a summary of how + * many pings got returned. + * If the node was not pinging at the time of the method-call, this method does + * nothing. + * + * @param arg + */ +void stop(char * arg); + +#endif /* PING_TEST_H */ From d2381df184c0f9bfa3db843c58f76f235845be04 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 11 Dec 2012 16:03:00 +0100 Subject: [PATCH 07/35] the simplest of pings is working --- projects/test_ping/main.c | 225 ++++++++++++++++++++++++++++---------- projects/test_ping/main.h | 16 ++- 2 files changed, 183 insertions(+), 58 deletions(-) diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index 2039089d4e..2d97fa0959 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -1,19 +1,39 @@ #include +//standard stuff #include #include #include #include +//shell stuff #include #include #include #include + +//net stuff #include +#include -#define STACKSIZE KERNEL_CONF_STACKSIZE_DEFAULT +#define SHELL_STACK (2048) +#define RADIO_STACK (2048) -char stack[STACKSIZE]; +#define SND_BUFFER_SIZE (100) +#define RCV_BUFFER_SIZE (64) + +char stack_shell[SHELL_STACK]; +char stack_radio[RADIO_STACK]; + +uint8_t snd_buffer[SND_BUFFER_SIZE][CC1100_MAX_DATA_LENGTH]; + +msg_t msg_q[RCV_BUFFER_SIZE]; + +transceiver_command_t tcmd; +msg_t mesg; + +static int radio_pid; +static radio_packet_t p; // Shell commands for this application const shell_command_t shell_commands[] = @@ -32,65 +52,47 @@ int pid_pingthread = 0; // see header for documentation void init(char* arg) { - transceiver_command_t tcmd; - msg_t m; uint16_t addr = 0; uint16_t chan = 10; - printf("transceiver pid is %d.\n", transceiver_pid); - int res = sscanf(arg, "init %hu %hu", &addr, &chan); - if (res == 1) { - puts("Setting address, keeping default channel"); - - if (addr >= MIN_ADDR && addr <= MAX_ADDR - && chan >= MIN_CHAN && chan <= MAX_CHAN) { - //addr. given, channel should be default, which is 10 for us - //check for validity in any case, just to be sure - - - puts("Initializing 6lowpan.."); - sixlowpan_init(TRANSCEIVER_CC1100,addr,0); - puts("Address set, setting channel"); - - tcmd.data = &chan; - m.type = SET_CHANNEL; - m.content.ptr = (void*) &tcmd; - - puts("waiting for transceiver.."); - msg_send_receive(&m, &m, transceiver_pid); - puts("Channel set."); - - } else { - printf("ERROR: The address for the node has to be in %d to %d.\n", - MIN_ADDR, MAX_ADDR); - } - - } else if (res == 2) { + if (res > 0) { puts("Setting address and channel"); if (addr >= MIN_ADDR && addr <= MAX_ADDR && chan >= MIN_CHAN && chan <= MAX_CHAN) { - //addr. & channel are given, check validity + // check validity of address and channel - puts("Initializing 6lowpan.."); - sixlowpan_init(TRANSCEIVER_CC1100,addr,0); - puts("address set, setting channel"); + if (!radio_pid) { + radio_pid = thread_create(stack_radio, RADIO_STACK, + PRIORITY_MAIN - 2, CREATE_STACKTEST, radio, "radio"); + printf("radio pid is %d.\n", radio_pid); + } - tcmd.data = &chan; - m.type = SET_CHANNEL; - m.content.ptr = (void*) &tcmd; + if (!transceiver_pid) { + puts("starting up transceiver.."); + transceiver_init(TRANSCEIVER_CC1100); + transceiver_start(); + transceiver_register(TRANSCEIVER_CC1100, radio_pid); + puts("started and registered the transceiver."); + printf("transceiver pid is %d.\n", transceiver_pid); + } - puts("waiting for transceiver.."); - msg_send_receive(&m, &m, transceiver_pid); - puts("channel set"); + set_radio_address((uint8_t) addr); + set_radio_channel((uint8_t) chan); + + printf("radio address is %d\n", get_radio_address()); + puts("turning on.."); + + switch_to_rx(); + + puts("done"); } else { printf("ERROR: The address for the node has to be in %d to %d.\n", MIN_ADDR, MAX_ADDR); printf("ERROR: The channel for the node has to be in %d to %d.\n", MIN_CHAN, MAX_CHAN); } - //addr and channel given } else { //no correct argument given, but radio address is mandatory puts("Usage: init [radioaddr] (radiochannel)"); @@ -149,8 +151,82 @@ void help(char* cmdname) { } // see header for docs -void ping() { - //TODO implement +void ping(char* arg) { + uint16_t addr; + + int res = sscanf(arg, "ping %hu", &addr); + + if (res > 0) { + if (addr < MAX_ADDR) { + printf("Ready to send to address %d\n", addr); + //todo do something that makes sense actually + mesg.type = SND_PKT; + mesg.content.ptr = (char*) &tcmd; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &p; + + p.length = 4; + p.dst = addr; + + puts("sending.."); + p.data = "ping"; + msg_send(&mesg, transceiver_pid, 1); + puts("sent"); + } else { + printf("ERROR: Please give an address which is in range %d to %d.", + MIN_ADDR, MAX_ADDR); + } + } else { + puts("ERROR: Please give an address which you wish to ping."); + puts("For more information on how to use ping, type 'help ping'."); + } +} + +void set_radio_address(uint8_t address) { + uint16_t addr = (uint16_t) address; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &addr; + mesg.content.ptr = (char*) &tcmd; + mesg.type = SET_ADDRESS; + msg_send_receive(&mesg, &mesg, transceiver_pid); +} + +uint16_t get_radio_address(void) { + uint16_t result; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &result; + mesg.content.ptr = (char*) &tcmd; + mesg.type = GET_ADDRESS; + msg_send_receive(&mesg, &mesg, transceiver_pid); + return result; +} + +void set_radio_channel(uint8_t channel) { + uint16_t chan = (uint16_t) channel; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &chan; + mesg.content.ptr = (char*) &tcmd; + mesg.type = SET_CHANNEL; + msg_send_receive(&mesg, &mesg, transceiver_pid); +} + +void switch_to_rx(void) { + mesg.type = SWITCH_RX; + mesg.content.ptr = (char*) &tcmd; + tcmd.transceivers = TRANSCEIVER_CC1100; + msg_send(&mesg, transceiver_pid, 1); +} + +void powerdown(char *unused) { + mesg.type = POWERDOWN; + mesg.content.ptr = (char*) &tcmd; + + tcmd.transceivers = TRANSCEIVER_CC1100; + msg_send(&mesg, transceiver_pid, 1); } void stop(char* unused) { @@ -159,13 +235,49 @@ void stop(char* unused) { } } -void hellothread(){ - while(true){ - puts("Hello!"); - vtimer_usleep(1000*2000); //2secs +void radio(void) { + msg_t m; + radio_packet_t *p; + uint8_t i; + + msg_init_queue(msg_q, RCV_BUFFER_SIZE); + + while (1) { + msg_receive(&m); + if (m.type == PKT_PENDING) { + p = (radio_packet_t*) m.content.ptr; + printf("Packet waiting, process %p...\n", p); + printf("\tLength:\t%u\n", p->length); + printf("\tSrc:\t%u\n", p->src); + printf("\tDst:\t%u\n", p->dst); + printf("\tLQI:\t%u\n", p->lqi); + printf("\tRSSI:\t%u\n", p->rssi); + + for (i = 0; i < p->length; i++) { + printf("%02X ", p->data[i]); + } + p->processing--; + printf("\n"); + } + else if (m.type == ENOBUFFER) { + puts("Transceiver buffer full"); + } + else { + puts("Unknown packet received"); + } } } +//Runs the shell +void shell_runner(void) { + posix_open(uart0_handler_pid, 0); + + shell_t shell; + shell_init(&shell, shell_commands, uart0_readc, uart0_putc); + + shell_run(&shell); +} + /** * The main function for this application, starts the shell and waits for * commands. @@ -174,14 +286,13 @@ int main(void) { puts("Ping Test Application\n"); puts("For commands type 'help'!\n"); - thread_create(stack, STACKSIZE, PRIORITY_MAIN -3,8, hellothread,"hello"); + thread_create(stack_shell, SHELL_STACK, PRIORITY_MAIN - 1, + CREATE_STACKTEST, shell_runner, "shell"); - posix_open(uart0_handler_pid, 0); - - shell_t shell; - shell_init(&shell, shell_commands, uart0_readc, uart0_putc); - - shell_run(&shell); + while (true) { + //sleep a sec + vtimer_usleep(1000 * 1000); + } return 0; } diff --git a/projects/test_ping/main.h b/projects/test_ping/main.h index 6128b97e16..4f3d3f1e75 100644 --- a/projects/test_ping/main.h +++ b/projects/test_ping/main.h @@ -2,10 +2,14 @@ #define PING_TEST_H +#include + #define MIN_ADDR 1 #define MIN_CHAN MIN_ADDR #define MAX_CHAN 14 #define MAX_ADDR 255 +#define SND_BUFFER_SIZE (100) +#define RCV_BUFFER_SIZE (64) /** * @brief Shows a helping text. @@ -30,7 +34,15 @@ void init(char * arg); * Sends out pings from this node to another node in a continuous manner, until * the stop command is used. */ -void ping(); +//void ping(char * arg); + +//uint16_t get_radio_address(void); + +void set_radio_address(uint8_t addr); + +void set_radio_channel(uint8_t chan); + +void switch_to_rx(void); /** * Stops any current pinging-action by this node and prints a summary of how @@ -42,4 +54,6 @@ void ping(); */ void stop(char * arg); +void radio(void); + #endif /* PING_TEST_H */ From 04a336c0a298a1bdeede46ad6670e6d5fa462129 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 11 Dec 2012 16:04:05 +0100 Subject: [PATCH 08/35] commented stuff in again that was commed out --- projects/test_ping/main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/test_ping/main.h b/projects/test_ping/main.h index 4f3d3f1e75..d4a31a94e9 100644 --- a/projects/test_ping/main.h +++ b/projects/test_ping/main.h @@ -34,9 +34,9 @@ void init(char * arg); * Sends out pings from this node to another node in a continuous manner, until * the stop command is used. */ -//void ping(char * arg); +void ping(char * arg); -//uint16_t get_radio_address(void); +uint16_t get_radio_address(void); void set_radio_address(uint8_t addr); From 515302bce6e76b9be4ca721e12cddb60937867d4 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 18 Dec 2012 17:28:42 +0100 Subject: [PATCH 09/35] Pinging now works with ACK return, buggy though. TODO: kick swtimer out, use vtimer for rtt calcs --- projects/test_ping/Jamfile | 2 +- projects/test_ping/main.c | 82 ++++++--------- projects/test_ping/main.h | 49 +++++++-- projects/test_ping/pingpong.c | 193 ++++++++++++++++++++++++++++++++++ projects/test_ping/pingpong.h | 127 ++++++++++++++++++++++ 5 files changed, 396 insertions(+), 57 deletions(-) create mode 100644 projects/test_ping/pingpong.c create mode 100644 projects/test_ping/pingpong.h diff --git a/projects/test_ping/Jamfile b/projects/test_ping/Jamfile index 39a205aa69..45634863a6 100644 --- a/projects/test_ping/Jamfile +++ b/projects/test_ping/Jamfile @@ -1,5 +1,5 @@ SubDir TOP projects test_ping ; -Module test_ping : main.c : shell shell_commands ps uart0 posix_io auto_init vtimer 6lowpan cc110x transceiver ; +Module test_ping : main.c pingpong.c : shell shell_commands ps uart0 posix_io auto_init vtimer swtimer 6lowpan cc110x transceiver ; UseModule test_ping ; diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index 2d97fa0959..bf9e8c6a0e 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -15,8 +15,9 @@ //net stuff #include #include +#include -#define SHELL_STACK (2048) +#define SHELL_STACK (4500) #define RADIO_STACK (2048) #define SND_BUFFER_SIZE (100) @@ -32,8 +33,8 @@ msg_t msg_q[RCV_BUFFER_SIZE]; transceiver_command_t tcmd; msg_t mesg; +static bool isinit = false; static int radio_pid; -static radio_packet_t p; // Shell commands for this application const shell_command_t shell_commands[] = @@ -43,13 +44,10 @@ const shell_command_t shell_commands[] = init }, { "ping", "Makes this node a pinging node", ping }, { "stop", "Stops the current node's pings and prints a summary", - stop }, + stop_pings }, { NULL, NULL, NULL } }; -// pid of ongoing ping thread, 0 if not set -int pid_pingthread = 0; - // see header for documentation void init(char* arg) { uint16_t addr = 0; @@ -82,11 +80,7 @@ void init(char* arg) { set_radio_channel((uint8_t) chan); printf("radio address is %d\n", get_radio_address()); - puts("turning on.."); - - switch_to_rx(); - - puts("done"); + isinit = true; } else { printf("ERROR: The address for the node has to be in %d to %d.\n", MIN_ADDR, MAX_ADDR); @@ -150,29 +144,24 @@ void help(char* cmdname) { } } -// see header for docs +// see header for documentation void ping(char* arg) { uint16_t addr; + if (!isinit) { + // don't try to send without proper init + puts("[ERROR] Cannot send while radio is not initialized!"); + return; + } + int res = sscanf(arg, "ping %hu", &addr); if (res > 0) { if (addr < MAX_ADDR) { printf("Ready to send to address %d\n", addr); - //todo do something that makes sense actually - mesg.type = SND_PKT; - mesg.content.ptr = (char*) &tcmd; - tcmd.transceivers = TRANSCEIVER_CC1100; - tcmd.data = &p; + pingpong(addr, 5); - p.length = 4; - p.dst = addr; - - puts("sending.."); - p.data = "ping"; - msg_send(&mesg, transceiver_pid, 1); - puts("sent"); } else { printf("ERROR: Please give an address which is in range %d to %d.", MIN_ADDR, MAX_ADDR); @@ -183,6 +172,7 @@ void ping(char* arg) { } } +// see header for documentation void set_radio_address(uint8_t address) { uint16_t addr = (uint16_t) address; @@ -193,6 +183,7 @@ void set_radio_address(uint8_t address) { msg_send_receive(&mesg, &mesg, transceiver_pid); } +// see header for documentation uint16_t get_radio_address(void) { uint16_t result; @@ -204,6 +195,7 @@ uint16_t get_radio_address(void) { return result; } +// see header for documentation void set_radio_channel(uint8_t channel) { uint16_t chan = (uint16_t) channel; @@ -214,48 +206,42 @@ void set_radio_channel(uint8_t channel) { msg_send_receive(&mesg, &mesg, transceiver_pid); } -void switch_to_rx(void) { - mesg.type = SWITCH_RX; - mesg.content.ptr = (char*) &tcmd; - tcmd.transceivers = TRANSCEIVER_CC1100; - msg_send(&mesg, transceiver_pid, 1); -} - -void powerdown(char *unused) { - mesg.type = POWERDOWN; - mesg.content.ptr = (char*) &tcmd; - - tcmd.transceivers = TRANSCEIVER_CC1100; - msg_send(&mesg, transceiver_pid, 1); -} - -void stop(char* unused) { - //TODO implement - if (pid_pingthread) { - } +// see header for documentation +void stop_pings(char* unused) { + stop(); } +// see header for documentation void radio(void) { msg_t m; radio_packet_t *p; - uint8_t i; - + ping_packet_t *ping_pkt; msg_init_queue(msg_q, RCV_BUFFER_SIZE); while (1) { msg_receive(&m); + if (m.type == PKT_PENDING) { p = (radio_packet_t*) m.content.ptr; + ping_pkt = (ping_packet_t*) p->data; + printf("Packet waiting, process %p...\n", p); printf("\tLength:\t%u\n", p->length); printf("\tSrc:\t%u\n", p->src); printf("\tDst:\t%u\n", p->dst); printf("\tLQI:\t%u\n", p->lqi); printf("\tRSSI:\t%u\n", p->rssi); + printf("Type: %d, ", ping_pkt->type); + printf("Seq#: %d\n", ping_pkt->seq_nr); - for (i = 0; i < p->length; i++) { - printf("%02X ", p->data[i]); + if (ping_pkt->type == PING) { + ping_incoming((uint8_t) p->src); + } else if (ping_pkt->type == PING_ACK) { + ack_incoming(); + } else if (ping_pkt->type == PING_BCST) { + broadcast_incoming(); } + p->processing--; printf("\n"); } @@ -291,7 +277,7 @@ int main(void) { while (true) { //sleep a sec - vtimer_usleep(1000 * 1000); + vtimer_usleep(1 * SECOND); } return 0; diff --git a/projects/test_ping/main.h b/projects/test_ping/main.h index d4a31a94e9..70830b474c 100644 --- a/projects/test_ping/main.h +++ b/projects/test_ping/main.h @@ -3,11 +3,23 @@ #define PING_TEST_H #include +#include -#define MIN_ADDR 1 -#define MIN_CHAN MIN_ADDR -#define MAX_CHAN 14 -#define MAX_ADDR 255 +/** + * Maximum and minimum radio address + */ +#define MIN_ADDR MIN_UID +#define MAX_ADDR MAX_UID + +/** + * Maximum and minimum channel address + */ +#define MIN_CHAN MIN_CHANNR +#define MAX_CHAN MAX_CHANNR + +/** + * Receive- and send-buffer size + */ #define SND_BUFFER_SIZE (100) #define RCV_BUFFER_SIZE (64) @@ -36,24 +48,45 @@ void init(char * arg); */ void ping(char * arg); +/** + * @brief Returns the radio address of this device. + * + * @return The radio-address of the device. Undefined if radio-address has not + * been set properly before. + */ uint16_t get_radio_address(void); +/** + * @brief Sets the radio address of this device. It is undefined what happens + * if radio-address is not in valid range. + * + * @param addr The radio-address to set. + */ void set_radio_address(uint8_t addr); +/** + * @brief Sets the radio channel used for the pinging or broadcasting of nodes. + * It is undefined what happens if radio-address is not in valid range. + * + * @param chan The channel number to set. + */ void set_radio_channel(uint8_t chan); -void switch_to_rx(void); - /** + * @brief Stops this node from pinging. + * * Stops any current pinging-action by this node and prints a summary of how * many pings got returned. * If the node was not pinging at the time of the method-call, this method does * nothing. * - * @param arg + * @param arg unused */ -void stop(char * arg); +void stop_pings(char * arg); +/** + * @brief The thread for the processing of received radio-packets. + */ void radio(void); #endif /* PING_TEST_H */ diff --git a/projects/test_ping/pingpong.c b/projects/test_ping/pingpong.c new file mode 100644 index 0000000000..610616dbfa --- /dev/null +++ b/projects/test_ping/pingpong.c @@ -0,0 +1,193 @@ +//include thy header! +#include + +//standard stuff +#include +#include +#include +#include +#include +#include + +//net stuff +#include + +char stack_stop[XS_STACK]; + +static uint64_t start = 0; +static uint64_t end = 0; +static float rtt = 0; +static bool cont_ping = false; +static uint16_t time = 0; +static int wait_pid = 0; +static uint16_t sequence = 0; + +radio_packet_t p; +ping_packet_t ping_packet; +transceiver_command_t tcmd; +msg_t mesg; + +// see header for documentation +void stop_after_time() { + vtimer_usleep(time * SECOND); + stop(); +} + +// see header for documentation +void stop() { + cont_ping = false; +} + +// see header for documentation +void pingpong(uint8_t addr, uint16_t duration) { + cont_ping = true; + time = duration; + + if (time) { + //A time has been given after which pings should not be sent anymore + thread_create(stack_stop, XS_STACK, PRIORITY_MAIN - 2, CREATE_STACKTEST, + stop_after_time, "showstopper"); + } + while (cont_ping) { + start = swtimer_now(); + wait_pid = thread_getpid(); + send_ping(addr); + + wait_pong(); + //savestats(); + } + //We're done, print endstats + //printendstats(); +} + +// see header for documentation +void wait_pong() { + //Either sleep 2 seconds or get waken up in between + vtimer_usleep(2 * SECOND); + calc_rtt(); + if (rtt > 2000) { + //this means that the pong to this ping wasn't received + print_failure(); + } else { + print_success(); + } +} + +// see header for documentation +void broadcast_without_ack(uint16_t duration) { + time = duration; + + if (time) { + //A time has been given after which pings should not be sent anymore + thread_create(stack_stop, XS_STACK, PRIORITY_MAIN - 2, 0, + stop_after_time, "showstopper"); + } + + while (cont_ping) { + start = swtimer_now(); + send_broadcast(); + vtimer_usleep(500 * 1000); + } +} + +// see header for documentation +void ping_incoming(uint8_t src) { + puts("Ping in, sending ack out"); + send_ack(src); +} + +// see header for documentation +void ack_incoming() { + thread_wakeup(wait_pid); + puts("Ping got acked"); +} + +// see header for documentation +void broadcast_incoming() { + puts("got some broadcasted stuff"); +} + +// see header for documentation +void print_success() { + printf("%s%f%s\n", "time=", rtt, "ms"); +} + +// see header for documentation +void print_failure() { + puts("Time for ping exceeded"); +} + +// see header for documentation +void send_ping(uint8_t addr) { + + mesg.type = SND_PKT; + mesg.content.ptr = (char*) &tcmd; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &p; + p.length = sizeof(ping_packet_t); + p.dst = addr; + + puts("creating packet.."); + sequence++; + ping_packet.seq_nr = sequence; + ping_packet.type = PING; + + puts("sending ping.."); + printf("pingpacket address: %p", &ping_packet); + printf("pingpacket seqnr: %d", ping_packet.seq_nr); + printf("pingpacket type: %d\n", ping_packet.type); + thread_print_all(); + p.data = (uint8_t *) &ping_packet; + msg_send(&mesg, transceiver_pid, 1); + puts("sent"); + +} + +// see header for documentation +void send_ack(uint8_t addr) { + mesg.type = SND_PKT; + mesg.content.ptr = (char*) &tcmd; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &p; + p.length = sizeof(ping_packet_t); + p.dst = addr; + + puts("creating packet.."); + sequence++; + ping_packet.seq_nr = sequence; + ping_packet.type = PING_ACK; + + puts("sending ack.."); + p.data = (uint8_t *) &ping_packet; + msg_send(&mesg, transceiver_pid, 1); + puts("sent"); +} + +// see header for documentation +void send_broadcast() { + mesg.type = SND_PKT; + mesg.content.ptr = (char*) &tcmd; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &p; + p.length = sizeof(ping_packet_t); + p.dst = 0; + + puts("creating packet.."); + sequence++; + ping_packet.seq_nr = sequence; + ping_packet.type = PING_BCST; + + puts("sending broadcast.."); + p.data = (uint8_t *) &ping_packet; + msg_send(&mesg, transceiver_pid, 1); + puts("sent"); +} + +// see header for documentation +void calc_rtt() { + end = swtimer_now(); + rtt = ((float) end - (float) start) / 1000; +} diff --git a/projects/test_ping/pingpong.h b/projects/test_ping/pingpong.h new file mode 100644 index 0000000000..e388c2b894 --- /dev/null +++ b/projects/test_ping/pingpong.h @@ -0,0 +1,127 @@ +#ifndef PING_H +#define PING_H + +#include + +#define XS_STACK (400) +#define SECOND (1000*1000) + +/** + * The different message types a ping_packet_t message can have: + * PING means it is a normal pingmessage. + * PING_ACK means it is an ACK to one of those normal PING messages. + * PING_BCST means it is a broadcasted ping that doesn't care about ACKs. + */ +enum ping_message_type { + PING, //!< PING + PING_ACK, //!< PING_ACK + PING_BCST,//!< PING_BCST +}; + +/** + * The struckt describing a ping-packet. A pingpacket has a sequencenumber and + * a type. + */ +typedef struct __attribute__((packed)) { + uint16_t seq_nr; + uint8_t type ; +} ping_packet_t; + +/** + * @brief The method that sends a ping to an address addr for duration seconds. + * + * This method sends a ping to the given address addr for duration seconds. + * + * @param addr A radio address to send pings to. + * @param duration A duration in seconds. + */ +void pingpong(uint8_t addr, uint16_t duration); + +/** + * @brief Waits for an acknowledgment of a previously sent ping. + * + * This method is an internal method and should not be called from the outside. + */ +void wait_pong(); + +/** + * @brief Sends a broadcast for duration seconds. + * + * This method sends a broadcast for duration seconds with a delay of 500ms + * between each message. + * + * @param duration The duration for this broadcast to continue, in seconds. + */ +void broadcast_without_ack(uint16_t duration); + +/** + * @brief Handles incoming PING messages. + * + * @param src the source-address from which the pingmessage originated from. + */ +void ping_incoming(uint8_t src); + +/** + * @brief Handles incoming ACK messages. + */ +void ack_incoming(); + +/** + * @brief Handles incoming broadcast messages. + */ +void broadcast_incoming(); + +/** + * @brief The internal method for sending a pingmessage to address addr. + * @param addr The address to send a pingmessage to. + */ +void send_ping(uint8_t addr); + +/** + * @brief The internal method for sending an acknowledgment of a ping to address + * addr. + * + * @param addr The address to send an acknowledgment to. + */ +void send_ack(uint8_t addr); + +/** + * @brief The internal method for sending a broadcast message. + */ +void send_broadcast(); + +/** + * @brief The internal method to calculate the Round-Trip-Time for a ping. + */ +void calc_rtt(void); + +/** + * @brief The internal method to stop this node from pinging a target. + * + * This method should be used for example if a ping was given without a + * duration, so without manually stopping the node it would send endlessly. + */ +void stop(void); + +/** + * @brief The internal thread that stops this node from pinging a target after a + * specified time. + */ +void stop_after_time(void); + +/** + * @brief Prints a success message when a ping was sent and an ACK for it was + * returned. + * + * This method pings the Round-Trip-Time for a pingmessage to which an ACK was + * received. + */ +void print_success(); + +/** + * @brief Prints a failure message if a ping exceeds the timelimit for an ACK + * to be received. + */ +void print_failure(); + +#endif /* PING_H */ From 6d9416e32732b3f7f55f14b43e8f8ef217704cdb Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 8 Jan 2013 15:24:57 +0100 Subject: [PATCH 10/35] broadcasting works now --- projects/test_ping/main.c | 41 ++++++++++++++++++++++++++++++++--- projects/test_ping/main.h | 22 +++++++++++++++++-- projects/test_ping/pingpong.c | 12 +++++++--- projects/test_ping/pingpong.h | 4 ++-- 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index bf9e8c6a0e..a2eab0b0cd 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -42,9 +42,10 @@ const shell_command_t shell_commands[] = { "init", "Initializes this node with an address and a channel.", init }, + { "broadcast", "Puts this node into broadcast mode", broadcast }, { "ping", "Makes this node a pinging node", ping }, { "stop", "Stops the current node's pings and prints a summary", - stop_pings }, + stop }, { NULL, NULL, NULL } }; @@ -144,6 +145,37 @@ void help(char* cmdname) { } } +// see header for documentation +void broadcast(char* arg) { + uint16_t duration; + + if (!isinit) { + // don't try to send without proper init + puts("[ERROR] Cannot broadcast while radio is not initialized!"); + return; + } + + int res = sscanf(arg, "broadcast %hu", &duration); + + if (res > 0) { + if (duration < MAX_ADDR) { + printf("Ready to broadcast for a duration of %d seconds\n", + duration); + + broadcast_without_ack(duration); + + } else { + printf("ERROR: Please give a duration which is in range %d to %d.", + MIN_DURATION, MAX_DURATION); + } + } else { + puts("ERROR: Please give a duration for which you wish to broadcast."); + puts( + "For more information on how to use broadcast, type 'help broadcast'."); + } + +} + // see header for documentation void ping(char* arg) { uint16_t addr; @@ -207,8 +239,11 @@ void set_radio_channel(uint8_t channel) { } // see header for documentation -void stop_pings(char* unused) { - stop(); +void stop(char* unused) { + //TODO doesn't work, since broadcasting runs in the same thread, either del + //or make the whole thing threaded + puts("calling stop_now"); + stop_now(); } // see header for documentation diff --git a/projects/test_ping/main.h b/projects/test_ping/main.h index 70830b474c..aa0d2f2c35 100644 --- a/projects/test_ping/main.h +++ b/projects/test_ping/main.h @@ -17,6 +17,13 @@ #define MIN_CHAN MIN_CHANNR #define MAX_CHAN MAX_CHANNR +/** + * Maximum and minimum duration times + * TODO change min duration to 0 once stopping works as intended + */ +#define MIN_DURATION 1 +#define MAX_DURATION UINT16_MAX + /** * Receive- and send-buffer size */ @@ -40,6 +47,17 @@ void help(char * commandname); */ void init(char * arg); +/** + * @brief broadcasts for a specified duration + * + * Broadcasts a pingmessage from this node in a continuous manner until the + * duration (in seconds) is over or the stop command is used. + * If the duration is set to 0, it broadcasts endlessly until the stop command + * is used. + * @param arg + */ +void broadcast(char* arg); + /** * @brief Pings another node. * @@ -73,7 +91,7 @@ void set_radio_address(uint8_t addr); void set_radio_channel(uint8_t chan); /** - * @brief Stops this node from pinging. + * @brief Stops this node from sending broadcasts or pings. * * Stops any current pinging-action by this node and prints a summary of how * many pings got returned. @@ -82,7 +100,7 @@ void set_radio_channel(uint8_t chan); * * @param arg unused */ -void stop_pings(char * arg); +void stop(char * arg); /** * @brief The thread for the processing of received radio-packets. diff --git a/projects/test_ping/pingpong.c b/projects/test_ping/pingpong.c index 610616dbfa..5060e6ba58 100644 --- a/projects/test_ping/pingpong.c +++ b/projects/test_ping/pingpong.c @@ -30,11 +30,12 @@ msg_t mesg; // see header for documentation void stop_after_time() { vtimer_usleep(time * SECOND); - stop(); + stop_now(); } // see header for documentation -void stop() { +void stop_now() { + puts("stopping now"); cont_ping = false; } @@ -75,8 +76,10 @@ void wait_pong() { // see header for documentation void broadcast_without_ack(uint16_t duration) { + cont_ping = true; time = duration; + puts("Setting up broadcast"); if (time) { //A time has been given after which pings should not be sent anymore thread_create(stack_stop, XS_STACK, PRIORITY_MAIN - 2, 0, @@ -84,9 +87,11 @@ void broadcast_without_ack(uint16_t duration) { } while (cont_ping) { + puts("Setting up packet"); + //TODO replace swtimer with vtimer start = swtimer_now(); send_broadcast(); - vtimer_usleep(500 * 1000); + vtimer_usleep(1 * SECOND); } } @@ -167,6 +172,7 @@ void send_ack(uint8_t addr) { // see header for documentation void send_broadcast() { + puts("Preparing broadcast ping"); mesg.type = SND_PKT; mesg.content.ptr = (char*) &tcmd; diff --git a/projects/test_ping/pingpong.h b/projects/test_ping/pingpong.h index e388c2b894..267164ad7d 100644 --- a/projects/test_ping/pingpong.h +++ b/projects/test_ping/pingpong.h @@ -96,12 +96,12 @@ void send_broadcast(); void calc_rtt(void); /** - * @brief The internal method to stop this node from pinging a target. + * @brief The internal method to stop this node from pinging or broadcasting. * * This method should be used for example if a ping was given without a * duration, so without manually stopping the node it would send endlessly. */ -void stop(void); +void stop_now(void); /** * @brief The internal thread that stops this node from pinging a target after a From 525bc3f64a0c3e7e7150d2eae858204bd5cb90b7 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Mon, 28 Jan 2013 12:39:44 +0100 Subject: [PATCH 11/35] Ping entfernt, nur noch broadcast moeglich --- projects/test_ping/Jamfile | 2 +- projects/test_ping/main.c | 68 +--------------- projects/test_ping/main.h | 20 ----- projects/test_ping/pingpong.c | 148 ++-------------------------------- projects/test_ping/pingpong.h | 78 ------------------ 5 files changed, 9 insertions(+), 307 deletions(-) diff --git a/projects/test_ping/Jamfile b/projects/test_ping/Jamfile index 45634863a6..611e93593b 100644 --- a/projects/test_ping/Jamfile +++ b/projects/test_ping/Jamfile @@ -1,5 +1,5 @@ SubDir TOP projects test_ping ; -Module test_ping : main.c pingpong.c : shell shell_commands ps uart0 posix_io auto_init vtimer swtimer 6lowpan cc110x transceiver ; +Module test_ping : main.c pingpong.c : shell shell_commands ps uart0 posix_io auto_init vtimer cc110x transceiver ; UseModule test_ping ; diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index a2eab0b0cd..c59c6ca089 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -43,9 +43,6 @@ const shell_command_t shell_commands[] = "Initializes this node with an address and a channel.", init }, { "broadcast", "Puts this node into broadcast mode", broadcast }, - { "ping", "Makes this node a pinging node", ping }, - { "stop", "Stops the current node's pings and prints a summary", - stop }, { NULL, NULL, NULL } }; @@ -105,8 +102,6 @@ void help(char* cmdname) { puts("These are the usable commands:"); puts("\thelp (commandname)"); puts("\tinit [address] (channel)"); - puts("\tping [address] (time)"); - puts("\tstop"); puts(""); puts("[] = mandatory, () = optional"); } else if (!strcasecmp("init", command)) { @@ -119,29 +114,10 @@ void help(char* cmdname) { puts(" +---(channel): The radio-channel that this node should use"); puts(" This argument is optional."); puts(" Uses a default channel if not given."); - } else if (!strcasecmp("ping", command)) { - puts( - "ping: Sends ping-messages to another node and records statistics on the number"); - puts( - " + of sent messages/received messages as well as the RTT of those pings."); - puts(" +"); - puts( - " +---[address]: The radio-address that this node should send its pings to)"); - puts(" + This argument is mandatory."); - puts(" +"); - puts( - " +---(time) : The duration (in seconds) that these ping messages should "); - puts(" be sent over"); - puts(" This argument is optional."); - puts(" Sends infinite pings when no time is given."); - } else if (!strcasecmp("stop", command)) { - puts("stop: Stops any ongoing pings this node sends out."); - puts( - " If this node is currently not sending any pings, this command does nothing."); } else { puts("The command given was not recognized. You gave:"); puts(command); - puts("Recognized commands are 'init','ping' and 'stop'"); + puts("Recognized command is 'init'"); } } @@ -176,34 +152,6 @@ void broadcast(char* arg) { } -// see header for documentation -void ping(char* arg) { - uint16_t addr; - - if (!isinit) { - // don't try to send without proper init - puts("[ERROR] Cannot send while radio is not initialized!"); - return; - } - - int res = sscanf(arg, "ping %hu", &addr); - - if (res > 0) { - if (addr < MAX_ADDR) { - printf("Ready to send to address %d\n", addr); - - pingpong(addr, 5); - - } else { - printf("ERROR: Please give an address which is in range %d to %d.", - MIN_ADDR, MAX_ADDR); - } - } else { - puts("ERROR: Please give an address which you wish to ping."); - puts("For more information on how to use ping, type 'help ping'."); - } -} - // see header for documentation void set_radio_address(uint8_t address) { uint16_t addr = (uint16_t) address; @@ -238,14 +186,6 @@ void set_radio_channel(uint8_t channel) { msg_send_receive(&mesg, &mesg, transceiver_pid); } -// see header for documentation -void stop(char* unused) { - //TODO doesn't work, since broadcasting runs in the same thread, either del - //or make the whole thing threaded - puts("calling stop_now"); - stop_now(); -} - // see header for documentation void radio(void) { msg_t m; @@ -269,11 +209,7 @@ void radio(void) { printf("Type: %d, ", ping_pkt->type); printf("Seq#: %d\n", ping_pkt->seq_nr); - if (ping_pkt->type == PING) { - ping_incoming((uint8_t) p->src); - } else if (ping_pkt->type == PING_ACK) { - ack_incoming(); - } else if (ping_pkt->type == PING_BCST) { + if (ping_pkt->type == PING_BCST) { broadcast_incoming(); } diff --git a/projects/test_ping/main.h b/projects/test_ping/main.h index aa0d2f2c35..15cb0d075a 100644 --- a/projects/test_ping/main.h +++ b/projects/test_ping/main.h @@ -58,14 +58,6 @@ void init(char * arg); */ void broadcast(char* arg); -/** - * @brief Pings another node. - * - * Sends out pings from this node to another node in a continuous manner, until - * the stop command is used. - */ -void ping(char * arg); - /** * @brief Returns the radio address of this device. * @@ -90,18 +82,6 @@ void set_radio_address(uint8_t addr); */ void set_radio_channel(uint8_t chan); -/** - * @brief Stops this node from sending broadcasts or pings. - * - * Stops any current pinging-action by this node and prints a summary of how - * many pings got returned. - * If the node was not pinging at the time of the method-call, this method does - * nothing. - * - * @param arg unused - */ -void stop(char * arg); - /** * @brief The thread for the processing of received radio-packets. */ diff --git a/projects/test_ping/pingpong.c b/projects/test_ping/pingpong.c index 5060e6ba58..55f775148e 100644 --- a/projects/test_ping/pingpong.c +++ b/projects/test_ping/pingpong.c @@ -7,19 +7,10 @@ #include #include #include -#include //net stuff #include -char stack_stop[XS_STACK]; - -static uint64_t start = 0; -static uint64_t end = 0; -static float rtt = 0; -static bool cont_ping = false; -static uint16_t time = 0; -static int wait_pid = 0; static uint16_t sequence = 0; radio_packet_t p; @@ -27,149 +18,28 @@ ping_packet_t ping_packet; transceiver_command_t tcmd; msg_t mesg; -// see header for documentation -void stop_after_time() { - vtimer_usleep(time * SECOND); - stop_now(); -} - -// see header for documentation -void stop_now() { - puts("stopping now"); - cont_ping = false; -} - -// see header for documentation -void pingpong(uint8_t addr, uint16_t duration) { - cont_ping = true; - time = duration; - - if (time) { - //A time has been given after which pings should not be sent anymore - thread_create(stack_stop, XS_STACK, PRIORITY_MAIN - 2, CREATE_STACKTEST, - stop_after_time, "showstopper"); - } - while (cont_ping) { - start = swtimer_now(); - wait_pid = thread_getpid(); - send_ping(addr); - - wait_pong(); - //savestats(); - } - //We're done, print endstats - //printendstats(); -} - -// see header for documentation -void wait_pong() { - //Either sleep 2 seconds or get waken up in between - vtimer_usleep(2 * SECOND); - calc_rtt(); - if (rtt > 2000) { - //this means that the pong to this ping wasn't received - print_failure(); - } else { - print_success(); - } -} - // see header for documentation void broadcast_without_ack(uint16_t duration) { - cont_ping = true; - time = duration; + uint8_t counter = 0; + uint16_t seconds = 10; puts("Setting up broadcast"); - if (time) { - //A time has been given after which pings should not be sent anymore - thread_create(stack_stop, XS_STACK, PRIORITY_MAIN - 2, 0, - stop_after_time, "showstopper"); + if (duration > 0) { + seconds = duration; } - while (cont_ping) { - puts("Setting up packet"); - //TODO replace swtimer with vtimer - start = swtimer_now(); + while(counter < seconds){ + puts("Setting up packet"); send_broadcast(); vtimer_usleep(1 * SECOND); } } -// see header for documentation -void ping_incoming(uint8_t src) { - puts("Ping in, sending ack out"); - send_ack(src); -} - -// see header for documentation -void ack_incoming() { - thread_wakeup(wait_pid); - puts("Ping got acked"); -} - // see header for documentation void broadcast_incoming() { puts("got some broadcasted stuff"); } -// see header for documentation -void print_success() { - printf("%s%f%s\n", "time=", rtt, "ms"); -} - -// see header for documentation -void print_failure() { - puts("Time for ping exceeded"); -} - -// see header for documentation -void send_ping(uint8_t addr) { - - mesg.type = SND_PKT; - mesg.content.ptr = (char*) &tcmd; - - tcmd.transceivers = TRANSCEIVER_CC1100; - tcmd.data = &p; - p.length = sizeof(ping_packet_t); - p.dst = addr; - - puts("creating packet.."); - sequence++; - ping_packet.seq_nr = sequence; - ping_packet.type = PING; - - puts("sending ping.."); - printf("pingpacket address: %p", &ping_packet); - printf("pingpacket seqnr: %d", ping_packet.seq_nr); - printf("pingpacket type: %d\n", ping_packet.type); - thread_print_all(); - p.data = (uint8_t *) &ping_packet; - msg_send(&mesg, transceiver_pid, 1); - puts("sent"); - -} - -// see header for documentation -void send_ack(uint8_t addr) { - mesg.type = SND_PKT; - mesg.content.ptr = (char*) &tcmd; - - tcmd.transceivers = TRANSCEIVER_CC1100; - tcmd.data = &p; - p.length = sizeof(ping_packet_t); - p.dst = addr; - - puts("creating packet.."); - sequence++; - ping_packet.seq_nr = sequence; - ping_packet.type = PING_ACK; - - puts("sending ack.."); - p.data = (uint8_t *) &ping_packet; - msg_send(&mesg, transceiver_pid, 1); - puts("sent"); -} - // see header for documentation void send_broadcast() { puts("Preparing broadcast ping"); @@ -191,9 +61,3 @@ void send_broadcast() { msg_send(&mesg, transceiver_pid, 1); puts("sent"); } - -// see header for documentation -void calc_rtt() { - end = swtimer_now(); - rtt = ((float) end - (float) start) / 1000; -} diff --git a/projects/test_ping/pingpong.h b/projects/test_ping/pingpong.h index 267164ad7d..38cbe5f6e3 100644 --- a/projects/test_ping/pingpong.h +++ b/projects/test_ping/pingpong.h @@ -3,7 +3,6 @@ #include -#define XS_STACK (400) #define SECOND (1000*1000) /** @@ -27,23 +26,6 @@ typedef struct __attribute__((packed)) { uint8_t type ; } ping_packet_t; -/** - * @brief The method that sends a ping to an address addr for duration seconds. - * - * This method sends a ping to the given address addr for duration seconds. - * - * @param addr A radio address to send pings to. - * @param duration A duration in seconds. - */ -void pingpong(uint8_t addr, uint16_t duration); - -/** - * @brief Waits for an acknowledgment of a previously sent ping. - * - * This method is an internal method and should not be called from the outside. - */ -void wait_pong(); - /** * @brief Sends a broadcast for duration seconds. * @@ -54,74 +36,14 @@ void wait_pong(); */ void broadcast_without_ack(uint16_t duration); -/** - * @brief Handles incoming PING messages. - * - * @param src the source-address from which the pingmessage originated from. - */ -void ping_incoming(uint8_t src); - -/** - * @brief Handles incoming ACK messages. - */ -void ack_incoming(); - /** * @brief Handles incoming broadcast messages. */ void broadcast_incoming(); -/** - * @brief The internal method for sending a pingmessage to address addr. - * @param addr The address to send a pingmessage to. - */ -void send_ping(uint8_t addr); - -/** - * @brief The internal method for sending an acknowledgment of a ping to address - * addr. - * - * @param addr The address to send an acknowledgment to. - */ -void send_ack(uint8_t addr); - /** * @brief The internal method for sending a broadcast message. */ void send_broadcast(); -/** - * @brief The internal method to calculate the Round-Trip-Time for a ping. - */ -void calc_rtt(void); - -/** - * @brief The internal method to stop this node from pinging or broadcasting. - * - * This method should be used for example if a ping was given without a - * duration, so without manually stopping the node it would send endlessly. - */ -void stop_now(void); - -/** - * @brief The internal thread that stops this node from pinging a target after a - * specified time. - */ -void stop_after_time(void); - -/** - * @brief Prints a success message when a ping was sent and an ACK for it was - * returned. - * - * This method pings the Round-Trip-Time for a pingmessage to which an ACK was - * received. - */ -void print_success(); - -/** - * @brief Prints a failure message if a ping exceeds the timelimit for an ACK - * to be received. - */ -void print_failure(); - #endif /* PING_H */ From e8d71341f98829e2438f61f1f430121e999be765 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Mon, 28 Jan 2013 13:30:47 +0100 Subject: [PATCH 12/35] Counter wird wieder hochgezaehlt --- projects/test_ping/Jamfile | 2 +- projects/test_ping/pingpong.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/test_ping/Jamfile b/projects/test_ping/Jamfile index 611e93593b..c6df6d5dda 100644 --- a/projects/test_ping/Jamfile +++ b/projects/test_ping/Jamfile @@ -1,5 +1,5 @@ SubDir TOP projects test_ping ; -Module test_ping : main.c pingpong.c : shell shell_commands ps uart0 posix_io auto_init vtimer cc110x transceiver ; +Module test_ping : main.c pingpong.c : shell shell_commands ps uart0 posix_io auto_init vtimer 6lowpan cc110x transceiver ; UseModule test_ping ; diff --git a/projects/test_ping/pingpong.c b/projects/test_ping/pingpong.c index 55f775148e..f4d7e67599 100644 --- a/projects/test_ping/pingpong.c +++ b/projects/test_ping/pingpong.c @@ -30,6 +30,7 @@ void broadcast_without_ack(uint16_t duration) { while(counter < seconds){ puts("Setting up packet"); + counter = counter + 1; send_broadcast(); vtimer_usleep(1 * SECOND); } From 96baf6000f069bad96d573e3f61374bbdc977049 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Wed, 30 Jan 2013 18:56:23 +0100 Subject: [PATCH 13/35] added missing 'stopping now' message --- projects/test_ping/pingpong.c | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/test_ping/pingpong.c b/projects/test_ping/pingpong.c index f4d7e67599..6e0bdb2882 100644 --- a/projects/test_ping/pingpong.c +++ b/projects/test_ping/pingpong.c @@ -34,6 +34,7 @@ void broadcast_without_ack(uint16_t duration) { send_broadcast(); vtimer_usleep(1 * SECOND); } + puts("stopping now"); } // see header for documentation From 29e5e713b275acbc3feb9699a30ba10fbf8aa82e Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Wed, 13 Feb 2013 14:56:46 +0100 Subject: [PATCH 14/35] added debug functionality to ping-test --- projects/test_ping/main.c | 11 +++++++++++ projects/test_ping/pingpong.c | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index c59c6ca089..5dbc94fdc8 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -17,6 +17,12 @@ #include #include +//debug stuff +//#define ENABLE_DEBUG +#ifdef ENABLE_DEBUG +#include +#endif + #define SHELL_STACK (4500) #define RADIO_STACK (2048) @@ -247,6 +253,11 @@ int main(void) { CREATE_STACKTEST, shell_runner, "shell"); while (true) { +#ifdef ENABLE_DEBUG + thread_print_all(); + vtimer_print_short_queue(); + vtimer_print_long_queue(); +#endif //sleep a sec vtimer_usleep(1 * SECOND); } diff --git a/projects/test_ping/pingpong.c b/projects/test_ping/pingpong.c index 6e0bdb2882..34a41c6c59 100644 --- a/projects/test_ping/pingpong.c +++ b/projects/test_ping/pingpong.c @@ -11,6 +11,12 @@ //net stuff #include +//debug stuff +//#define ENABLE_DEBUG +#ifdef ENABLE_DEBUG +#include +#endif + static uint16_t sequence = 0; radio_packet_t p; @@ -32,6 +38,11 @@ void broadcast_without_ack(uint16_t duration) { puts("Setting up packet"); counter = counter + 1; send_broadcast(); +#ifdef ENABLE_DEBUG + thread_print_all(); + vtimer_print_short_queue(); + vtimer_print_long_queue(); +#endif vtimer_usleep(1 * SECOND); } puts("stopping now"); From 39482f73161e290637aa6f379e69783d729e5fd9 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Wed, 13 Feb 2013 14:59:15 +0100 Subject: [PATCH 15/35] deleted empty files objective_functions.c/h --- sys/net/sixlowpan/rpl/objective_functions.c | 6 ------ sys/net/sixlowpan/rpl/objective_functions.h | 3 --- 2 files changed, 9 deletions(-) delete mode 100644 sys/net/sixlowpan/rpl/objective_functions.c delete mode 100644 sys/net/sixlowpan/rpl/objective_functions.h diff --git a/sys/net/sixlowpan/rpl/objective_functions.c b/sys/net/sixlowpan/rpl/objective_functions.c deleted file mode 100644 index 96cb486731..0000000000 --- a/sys/net/sixlowpan/rpl/objective_functions.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "objective_functions.h" - -void of0(){ - - -} diff --git a/sys/net/sixlowpan/rpl/objective_functions.h b/sys/net/sixlowpan/rpl/objective_functions.h deleted file mode 100644 index a6acfb0a3c..0000000000 --- a/sys/net/sixlowpan/rpl/objective_functions.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -void of0(); From 567be35fc427fa6994802304dcac0fa97688ea37 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Wed, 13 Feb 2013 15:00:43 +0100 Subject: [PATCH 16/35] startet implementation of objective function mrhof --- sys/net/sixlowpan/rpl/of_mrhof.c | 56 ++++++++++++++++++++++++++++++++ sys/net/sixlowpan/rpl/of_mrhof.h | 28 ++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 sys/net/sixlowpan/rpl/of_mrhof.c create mode 100644 sys/net/sixlowpan/rpl/of_mrhof.h diff --git a/sys/net/sixlowpan/rpl/of_mrhof.c b/sys/net/sixlowpan/rpl/of_mrhof.c new file mode 100644 index 0000000000..801a9ebf7c --- /dev/null +++ b/sys/net/sixlowpan/rpl/of_mrhof.c @@ -0,0 +1,56 @@ +#include +#include "of_mrhof.h" + +rpl_of_t rpl_of_mrhof = { + 0x1, + calc_rank, + which_parent, + which_dodag, + reset, + NULL +}; + +rpl_of_t *rpl_get_of_mrhof(){ + return &rpl_of_mrhof; +} + +void reset(rpl_dodag_t *dodag){ + if(PARENT_SET_SIZE > 3){ + //do stuff + } + //todo implement if necessary +} + +uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank){ + if(base_rank == 0) { + if(parent == NULL) { + return INFINITE_RANK; + } + base_rank = parent->rank; + } + + uint16_t add; + if(parent != NULL){ + add = parent->dodag->minhoprankincrease; + } + else{ + add = DEFAULT_MIN_HOP_RANK_INCREASE; + } + if( base_rank + add < base_rank ){ + return INFINITE_RANK; + } + return base_rank + add; +} + +//We simply return the Parent with lower rank +rpl_parent_t * which_parent(rpl_parent_t *p1, rpl_parent_t *p2){ + if(p1->rank < p2->rank){ + return p1; + } + return p2; +} + +//Not used yet, as the implementation only makes use of one dodag for now. +rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2){ + return d1; +} diff --git a/sys/net/sixlowpan/rpl/of_mrhof.h b/sys/net/sixlowpan/rpl/of_mrhof.h new file mode 100644 index 0000000000..846da62128 --- /dev/null +++ b/sys/net/sixlowpan/rpl/of_mrhof.h @@ -0,0 +1,28 @@ +#include "rpl_structs.h" + +// Disallow links with greater than 4 expected +// transmission counts on the selected path. +#define MAX_LINK_METRIC (512) + +// Disallow paths with greater than 256 +// expected transmission counts. +#define MAX_PATH_COST (32768) + +// Switch to a new path only if it is +// expected to require at least 1.5 fewer transmissions than the +// current path. +#define PARENT_SWITCH_THRESHOLD (192) + +// If the preferred parent is not available, two +// candidate parents are still available without triggering a new +// round of route discovery. +#define PARENT_SET_SIZE (3) + +// Do not allow a node to become a floating root. +#define ALLOW_FLOATING_ROOT (0) + +rpl_of_t *rpl_get_of_mrhof(); +uint16_t calc_rank(rpl_parent_t *, uint16_t); +rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); +rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *); +void reset(rpl_dodag_t *); From 91b023df4bc73a705c7168e415297a82cbd1adc8 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Wed, 13 Feb 2013 15:02:21 +0100 Subject: [PATCH 17/35] deleted fake rounting entries which had been commented out --- sys/net/sixlowpan/rpl/rpl.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/sys/net/sixlowpan/rpl/rpl.c b/sys/net/sixlowpan/rpl/rpl.c index 12c6b7f332..7359bb9387 100644 --- a/sys/net/sixlowpan/rpl/rpl.c +++ b/sys/net/sixlowpan/rpl/rpl.c @@ -156,7 +156,7 @@ uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address){ //INSERT NEW OBJECTIVE FUNCTIONS HERE objective_functions[0] = rpl_get_of0(); - //objective_functions[1] = rpl_get_of_ETX() + objective_functions[1] = rpl_get_of_mrhof(); sixlowpan_init(trans,rpl_address,0); //Wir benötigen einen Link Local prefix, um unsere entsprechende Addresse im Netz abzufragen @@ -165,25 +165,6 @@ uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address){ ipv6_get_saddr(&my_address, &ll_address); set_rpl_process_pid(rpl_process_pid); - //some fake routing entries... - /*if(rpl_address != 1){ - ll_address.uint8[15]=1; - rpl_add_routing_entry(&ll_address, &ll_address, 9000); - ll_address.uint8[15]=2; - rpl_add_routing_entry(&ll_address, &ll_address, 8000); - ll_address.uint8[15]=3; - rpl_add_routing_entry(&ll_address, &ll_address, 7000); - ll_address.uint8[15]=4; - rpl_add_routing_entry(&ll_address, &ll_address, 6000); - ll_address.uint8[15]=5; - rpl_add_routing_entry(&ll_address, &ll_address, 5000); - ll_address.uint8[15]=6; - rpl_add_routing_entry(&ll_address, &ll_address, 4000); - ll_address.uint8[15]=7; - rpl_add_routing_entry(&ll_address, &ll_address, 4000); - ll_address.uint8[15]=8; - rpl_add_routing_entry(&ll_address, &ll_address, 4000); - } */ return SUCCESS; } @@ -797,6 +778,7 @@ void recv_rpl_dao_ack(void){ } +//xxx tcp_socket unused? 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(); From e0a21b9ddd9d7a03a5272d694ba4e99d42927c54 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Wed, 13 Feb 2013 15:03:16 +0100 Subject: [PATCH 18/35] added comments onto structs for easier findings in RFC --- sys/net/sixlowpan/rpl/rpl_structs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index c9e95dad1b..ee4bb737a4 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -98,6 +98,7 @@ #define RPL_GROUNDED_SHIFT 7 #define RPL_DEFAULT_OCP 0 +//DIO Base Object (RFC 6550 Fig. 14) struct __attribute__((packed)) rpl_dio_t{ uint8_t rpl_instanceid; uint8_t version_number; @@ -114,6 +115,7 @@ struct __attribute__((packed)) rpl_dis_t{ uint8_t reserved; }; +//DAO Base Object (RFC 6550 Fig. 16) struct __attribute__((packed)) rpl_dao_t{ uint8_t rpl_instanceid; uint8_t k_d_flags; @@ -121,6 +123,7 @@ struct __attribute__((packed)) rpl_dao_t{ uint8_t dao_sequence; }; +//DAO ACK Base Object (RFC 6550 Fig. 17.) struct __attribute__((packed)) rpl_dao_ack_t{ uint8_t rpl_instanceid; uint8_t d_reserved; @@ -128,15 +131,19 @@ struct __attribute__((packed)) rpl_dao_ack_t{ uint8_t status; }; +//DODAG ID Struckt //may be present in dao or dao_ack packets struct __attribute__((packed)) dodag_id_t{ ipv6_addr_t dodagid; }; + +//RPL-Option Generic Format (RFC 6550 Fig. 19) typedef struct __attribute__((packed)) rpl_opt_t { uint8_t type; uint8_t length; } rpl_opt_t; +//DODAG Configuration-Option (RFC 6550 Fig. 24) typedef struct __attribute__((packed)) rpl_opt_dodag_conf_t { uint8_t type; uint8_t length; @@ -152,6 +159,7 @@ typedef struct __attribute__((packed)) rpl_opt_dodag_conf_t { uint16_t lifetime_unit; } rpl_opt_dodag_conf_t; +//RPL Solicited Information Option (RFC 6550 Fig. 28) typedef struct __attribute__((packed)) rpl_opt_solicited_t { uint8_t type; uint8_t length; @@ -161,6 +169,7 @@ typedef struct __attribute__((packed)) rpl_opt_solicited_t { uint8_t version; } rpl_opt_solicited_t; +//RPL Target-Option (RFC 6550 Fig. 25) //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; @@ -170,6 +179,7 @@ typedef struct __attribute__((packed)) rpl_opt_target_t { ipv6_addr_t target; } rpl_opt_target_t; +//RPL Transit-Option (RFC 6550 Fig. 26) typedef struct __attribute__((packed)) rpl_opt_transit_t { uint8_t type; uint8_t length; From 644d6de3640c78867449a7827912548303b3d563 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Thu, 21 Feb 2013 18:23:36 +0100 Subject: [PATCH 19/35] changed rank calculation in OF0 and some other things. WARNING: this commit might break the rpl implementation for now, if a rollback is needed, choose an earlier commit than this --- sys/net/sixlowpan/rpl/of0.c | 19 ++++++++++++++----- sys/net/sixlowpan/rpl/of0.h | 2 +- sys/net/sixlowpan/rpl/rpl.c | 13 ++++++++++++- sys/net/sixlowpan/rpl/rpl_dodag.c | 12 ++++++++++-- sys/net/sixlowpan/rpl/rpl_structs.h | 18 ++++++++++++------ 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/sys/net/sixlowpan/rpl/of0.c b/sys/net/sixlowpan/rpl/of0.c index 3d0271842f..815a618379 100644 --- a/sys/net/sixlowpan/rpl/of0.c +++ b/sys/net/sixlowpan/rpl/of0.c @@ -7,6 +7,8 @@ rpl_of_t rpl_of0 = { which_parent, which_dodag, reset, + NULL, + NULL, NULL }; @@ -18,12 +20,19 @@ void reset(rpl_dodag_t *dodag){ //Nothing to do in OF0 } -uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank){ - if(base_rank == 0) { +uint16_t calc_rank(){ + rpl_parent_t * parent = rpl_find_preferred_parent(); + uint16_t my_rank = rpl_get_my_dodag()->my_rank; + + if(i_am_root){ + return rpl_get_my_dodag()->minhoprankincrease; + } + + if(my_rank == 0) { if(parent == NULL) { return INFINITE_RANK; } - base_rank = parent->rank; + my_rank = parent->rank; } uint16_t add; @@ -33,10 +42,10 @@ uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank){ else{ add = DEFAULT_MIN_HOP_RANK_INCREASE; } - if( base_rank + add < base_rank ){ + if( my_rank + add < my_rank ){ return INFINITE_RANK; } - return base_rank + add; + return my_rank + add; } //We simply return the Parent with lower rank diff --git a/sys/net/sixlowpan/rpl/of0.h b/sys/net/sixlowpan/rpl/of0.h index f31ec693e5..2d3029039f 100644 --- a/sys/net/sixlowpan/rpl/of0.h +++ b/sys/net/sixlowpan/rpl/of0.h @@ -1,7 +1,7 @@ #include "rpl_structs.h" rpl_of_t *rpl_get_of0(); -uint16_t calc_rank(rpl_parent_t *, uint16_t); +uint16_t calc_rank(); rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *); void reset(rpl_dodag_t *); diff --git a/sys/net/sixlowpan/rpl/rpl.c b/sys/net/sixlowpan/rpl/rpl.c index 7359bb9387..c2c76f1ec3 100644 --- a/sys/net/sixlowpan/rpl/rpl.c +++ b/sys/net/sixlowpan/rpl/rpl.c @@ -197,9 +197,15 @@ void rpl_init_root(){ dodag->lifetime_unit = RPL_LIFETIME_UNIT; dodag->version = RPL_COUNTER_INIT; dodag->grounded = RPL_GROUNDED; - dodag->my_rank = RPL_ROOT_RANK; + dodag->my_rank = ROOT_RANK; //TODO change this, according to spec. dodag->joined = 1; dodag->my_preferred_parent = NULL; + + //OF-specific initialisation, if needed. + //For non-root nodes, this happens when a DIO with a OF is received + if(dodag->of->init != NULL){ + dodag->of->init(); + } } else{ printf("Error - could not generate DODAG\n"); @@ -509,6 +515,7 @@ void recv_rpl_dio(void){ break; } case(RPL_OPT_DAG_METRIC_CONTAINER):{ + //TODO implement handling of Metric container len += rpl_opt_buf->length +2; break; } @@ -619,6 +626,10 @@ void recv_rpl_dio(void){ // Parent Handling // + //TODO parent selection should not be run from RPL core but from the object- + //ive function, the parents set here should be instead the candidate neigh- + //bor set + // //Ist Knoten bereits Parent? rpl_parent_t *parent; parent = rpl_find_parent(&ipv6_buf->srcaddr); diff --git a/sys/net/sixlowpan/rpl/rpl_dodag.c b/sys/net/sixlowpan/rpl/rpl_dodag.c index 912e2de692..71014f843c 100644 --- a/sys/net/sixlowpan/rpl/rpl_dodag.c +++ b/sys/net/sixlowpan/rpl/rpl_dodag.c @@ -7,6 +7,7 @@ rpl_instance_t instances[RPL_MAX_INSTANCES]; rpl_dodag_t dodags[RPL_MAX_DODAGS]; +rpl_candidate_neighbor_t candidates[RPL_MAX_CANDIDATE_NEIGHBORS]; rpl_parent_t parents[RPL_MAX_PARENTS]; rpl_instance_t *rpl_new_instance(uint8_t instanceid){ @@ -254,10 +255,17 @@ void rpl_join_dodag(rpl_dodag_t *dodag, ipv6_addr_t *parent, uint16_t parent_ran my_dodag->grounded = dodag->grounded; 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->my_rank = dodag->of->calc_rank(); my_dodag->dao_seq = RPL_COUNTER_INIT; my_dodag->min_rank = my_dodag->my_rank; + + //OF specific initialisation, the rootnode does this at the beginning + //when constructing a dodag + if(my_dodag->of->init != NULL){ + my_dodag->of->init(); + } + start_trickle(my_dodag->dio_min, my_dodag->dio_interval_doubling, my_dodag->dio_redundancy); delay_dao(); } @@ -278,7 +286,7 @@ void rpl_global_repair(rpl_dodag_t *dodag, ipv6_addr_t * p_addr, uint16_t rank){ my_dodag->my_rank = INFINITE_RANK; }else{ //Calc new Rank - my_dodag->my_rank = my_dodag->of->calc_rank(my_dodag->my_preferred_parent, my_dodag->my_rank); + my_dodag->my_rank = my_dodag->of->calc_rank(); my_dodag->min_rank = my_dodag->my_rank; reset_trickletimer(); delay_dao(); diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index ee4bb737a4..45eb4d43d5 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -59,7 +59,6 @@ // RPL Constants and Variables #define BASE_RANK 0 -#define ROOT_RANK 1 #define INFINITE_RANK 0xFFFF #define RPL_DEFAULT_INSTANCE 0 #define DEFAULT_PATH_CONTROL_SIZE 0 @@ -71,6 +70,7 @@ //#define DEFAULT_DIO_INTERVAL_DOUBLINGS 20 #define DEFAULT_DIO_REDUNDANCY_CONSTANT 10 #define DEFAULT_MIN_HOP_RANK_INCREASE 256 +#define ROOT_RANK DEFAULT_MIN_HOP_RANK_INCREASE //DAO_DELAY is in seconds #define DEFAULT_DAO_DELAY 3 #define REGULAR_DAO_INTERVAL 300 @@ -80,9 +80,10 @@ //others -#define NUMBER_IMPLEMENTED_OFS 1 +#define NUMBER_IMPLEMENTED_OFS 2 #define RPL_MAX_DODAGS 3 #define RPL_MAX_INSTANCES 1 +#define RPL_MAX_CANDIDATE_NEIGHBORS 15 #define RPL_MAX_PARENTS 5 #define RPL_MAX_ROUTING_ENTRIES 128 #define RPL_ROOT_RANK 1 @@ -191,6 +192,12 @@ typedef struct __attribute__((packed)) rpl_opt_transit_t { struct rpl_dodag_t; +typedef struct rpl_candidate_neighbor_t { + ipv6_addr_t addr; + struct rpl_dodag_t *dodag; + uint8_t used; +} rpl_candidate_neighbor_t; + typedef struct rpl_parent_t { ipv6_addr_t addr; uint16_t rank; @@ -200,8 +207,6 @@ typedef struct rpl_parent_t { uint8_t used; } rpl_parent_t; -struct rpl_of_t; - typedef struct rpl_instance_t { //struct rpl_dodag_t *current_dodoag; uint8_t id; @@ -232,16 +237,17 @@ typedef struct rpl_dodag_t { uint8_t joined; rpl_parent_t *my_preferred_parent; struct rpl_of_t *of; - } rpl_dodag_t; typedef struct rpl_of_t { uint16_t ocp; - uint16_t (*calc_rank)(rpl_parent_t *, uint16_t); + uint16_t (*calc_rank)(); rpl_parent_t *(*which_parent)(rpl_parent_t *, rpl_parent_t *); rpl_dodag_t *(*which_dodag)(rpl_dodag_t *, rpl_dodag_t *); void (*reset)(struct rpl_dodag_t *); void (*parent_state_callback)(rpl_parent_t *, int, int); + void (*init) (void); //OF specific init function + void (*process_dio) (); //DIO processing callback (acc. to OF0 spec, chpt 5) } rpl_of_t; typedef struct rpl_routing_entry_t { From 31b65059a8fe2eb30c2eafde94a76648558b5eec Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Thu, 21 Feb 2013 18:25:35 +0100 Subject: [PATCH 20/35] preparing for changing how parent selection/updates work in rpl, since the way it is implemented now goes against the spec --- sys/net/sixlowpan/rpl/of_mrhof.c | 188 ++++++++++++++++++++++++++----- sys/net/sixlowpan/rpl/of_mrhof.h | 27 ++++- 2 files changed, 180 insertions(+), 35 deletions(-) diff --git a/sys/net/sixlowpan/rpl/of_mrhof.c b/sys/net/sixlowpan/rpl/of_mrhof.c index 801a9ebf7c..91b5978cf4 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.c +++ b/sys/net/sixlowpan/rpl/of_mrhof.c @@ -1,56 +1,182 @@ #include +#include #include "of_mrhof.h" +static char is_initialised = 0; + +uint16_t cur_min_path_cost = MAX_PATH_COST; +static mrhof_candidate_info_t candidate_info[RPL_MAX_CANDIDATE_NEIGHBORS]; + rpl_of_t rpl_of_mrhof = { - 0x1, - calc_rank, - which_parent, - which_dodag, - reset, - NULL + 0x1, + calc_rank, + which_parent, + which_dodag, + reset, + init, + NULL }; -rpl_of_t *rpl_get_of_mrhof(){ +rpl_of_t *rpl_get_of_mrhof() { return &rpl_of_mrhof; } -void reset(rpl_dodag_t *dodag){ - if(PARENT_SET_SIZE > 3){ - //do stuff +void init() { + //TODO implement OF-specific init of timers/functions/structs/whatever + if (!is_initialised) { + //blabla init this node } + is_initialised = 1; +} + +void reset(rpl_dodag_t *dodag) { //todo implement if necessary } -uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank){ - if(base_rank == 0) { - if(parent == NULL) { - return INFINITE_RANK; - } - base_rank = parent->rank; +void calc_path_cost() { + /* + * Calculates the path cost through all candidate neighbours and sets + * cur_min_path_cost to the lowest value? + */ + + if(i_am_root){ + //Since for now we only support ETX, the pastcost that computes to + //a rank of minhoprankincrease IS minhoprankincrease + cur_min_path_cost = rpl_get_my_dodag()->minhoprankincrease; + return; } - uint16_t add; - if(parent != NULL){ - add = parent->dodag->minhoprankincrease; + /* + * This is the boolean describing if I need to do a parent selection. + * This happens always when the past cost for a candidate neighbor OR a + * parent changes. + */ + char do_parent_selection = 0; + uint16_t path_cost = 0; + for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + if(candidates[i].used){ + if(candidate_info[i].cur_etx != 0){ + /* The RFC specifies this computation a bit ambiguously, this is + * what I understood: + * + * (ETX_for_link_to_neighbor * 128) + Rank_of_that_neighbor + * + * This means I get the rank of that neighbor (which is the etx + * of the whole path from him to the root node) plus my ETX to + * that neighbor*128, which would be the 'rank' of the single link + * from me to that neighbor + * + */ + path_cost = candidate_info[i].cur_etx*ETX_RANK_MULTIPLIER + (candidates[i].dodag->my_rank); + if(candidate_info[i].cur_path_cost == path_cost){ + //nothing changed + continue; + } + do_parent_selection = 1; + candidate_info[i].cur_path_cost = path_cost; + }else{ + //if it is 0, the value has not been computed yet, so we can't + //compute a path cost + if(candidate_info[i].cur_path_cost == MAX_PATH_COST){ + //nothing changed + continue; + } + do_parent_selection = 1; + candidate_info[i].cur_path_cost = MAX_PATH_COST; + } + } } - else{ - add = DEFAULT_MIN_HOP_RANK_INCREASE; + if(do_parent_selection){ + parent_selection(); } - if( base_rank + add < base_rank ){ - return INFINITE_RANK; - } - return base_rank + add; + } -//We simply return the Parent with lower rank -rpl_parent_t * which_parent(rpl_parent_t *p1, rpl_parent_t *p2){ - if(p1->rank < p2->rank){ - return p1; +uint16_t calc_rank() { + /* + * Return the rank for this node (calculated from path cost). + * There will be 3 values calculated, the highest of those 3 values will be + * used as the noderank. + * + * For now, there is no metric-selection or specification, so the rank com- + * putation will always be assumed to be done for the ETX metric. + */ + uint16_t result = INFINITE_RANK; + + //Holds the 3 computed values for the nodes rank from which the max value + //will be the nodes actual rank + uint16_t rankarray[3] = {0,0,0}; + + //TODO finish this + //rankarray[0] = (rpl_find_preferred_parent()->rank > ; + + if (i_am_root) { + result = rpl_get_my_dodag()->minhoprankincrease; + return result; } - return p2; + + //Check which parent has the highest advertised rank + for (uint8_t i = 0; i < RPL_MAX_PARENTS; i++) { + if (parents[i].used) { + if (parents[i].rank == INFINITE_RANK){ + // parent not useful, should be deleted //TODO check if deletion + // should be triggered from here + continue; + } + else if (parents[i].rank > rankarray[2]) { + //store it away + rankarray[2] = parents[i].rank; + } + } + } + + //Compute 2nd rankvalue and store it in 2nd place in the array + if(rpl_get_my_dodag()->minhoprankincrease * (1 + (rankarray[2]/rpl_get_my_dodag()->minhoprankincrease)) < rankarray[2]){ + //overflow + rankarray[1] = INFINITE_RANK; + }else{ + rankarray[1] = rpl_get_my_dodag()->minhoprankincrease * (1 + (rankarray[2]/rpl_get_my_dodag()->minhoprankincrease)); + } + + //Compute the 3rd rankvalue and store it in the 3rd place + if(rankarray[2] - rpl_get_my_dodag()->maxrankincrease ) + + + return result; +} + +void parent_selection(){ + /* + * Select a candidate neighbor as preferred parent. + * + * Note: + * If we allow floating roots, a node may have no parents + */ + + /* + * Might be faster to set the node directly? + */ + uint8_t cur_min_path_neighbor_index = 0; + uint16_t min_path_cost = MAX_PATH_COST; + + for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + /* + * Go through all Candidate Neighbors, compare their path cost with cur- + * rent minimum path cost and change cur_min_path_neighbor_index + * to the index of the current neighbor if his path is 'shorter' + */ + if(candidates[i].used && (candidate_info[i].cur_path_cost < MAX_LINK_METRIC)){ + if(candidate_info[i].cur_path_cost < min_path_cost){ + cur_min_path_neighbor_index = i; + } + } + } + + //TODO finish this. + //rpl_find_preferred_parent() } //Not used yet, as the implementation only makes use of one dodag for now. -rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2){ +rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2) { return d1; } diff --git a/sys/net/sixlowpan/rpl/of_mrhof.h b/sys/net/sixlowpan/rpl/of_mrhof.h index 846da62128..ed4aa04377 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.h +++ b/sys/net/sixlowpan/rpl/of_mrhof.h @@ -6,23 +6,42 @@ // Disallow paths with greater than 256 // expected transmission counts. -#define MAX_PATH_COST (32768) +#define MAX_PATH_COST (0x8000) // Switch to a new path only if it is // expected to require at least 1.5 fewer transmissions than the // current path. #define PARENT_SWITCH_THRESHOLD (192) -// If the preferred parent is not available, two +// If the preferred parent is not available, some more // candidate parents are still available without triggering a new // round of route discovery. -#define PARENT_SET_SIZE (3) +#define PARENT_SET_SIZE (RPL_MAX_PARENTS) // Do not allow a node to become a floating root. #define ALLOW_FLOATING_ROOT (0) +// While assigning Rank when using ETX, use the representation of ETX described +// in [RFC6551], i.e., assign Rank equal to ETX * 128. +#define ETX_RANK_MULTIPLIER (0x80) + rpl_of_t *rpl_get_of_mrhof(); -uint16_t calc_rank(rpl_parent_t *, uint16_t); +uint16_t calc_rank(); +uint16_t calc_path_cost(); +uint16_t calc_etx_value(); rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *); void reset(rpl_dodag_t *); + +//############################ +// OF specific structs ####### +//############################ + +//neighbour struct for etx path calculation +typedef struct mrhof_candidate_info_t { + ipv6_addr_t addr; + uint16_t packet_snt; + uint16_t packet_rec; + uint16_t cur_path_cost; + uint16_t cur_etx; +} mrhof_candidate_info_t; From e8256783f47c75ab05a5dc2e43442f6f62c35d47 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Sun, 3 Mar 2013 17:47:11 +0100 Subject: [PATCH 21/35] added etx_beaconing files --- sys/net/sixlowpan/rpl/etx_beaconing.c | 153 ++++++++++++++++++++++++++ sys/net/sixlowpan/rpl/etx_beaconing.h | 36 ++++++ 2 files changed, 189 insertions(+) create mode 100644 sys/net/sixlowpan/rpl/etx_beaconing.c create mode 100644 sys/net/sixlowpan/rpl/etx_beaconing.h diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c new file mode 100644 index 0000000000..0c216e030d --- /dev/null +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -0,0 +1,153 @@ +/* + * etx_beaconing.c + * + * Created on: Feb 26, 2013 + * Author: stephan + */ +#include "etx_beaconing.h" + +#include +#include +#include + +#include +#include +#include + +#define MS 10000 + +unsigned int etx_beacon_pid; +unsigned int etx_radio_pid; + +//Buffer +char etx_beacon_buf[ETX_BEACON_STACKSIZE]; +char etx_radio_buf[ETX_BEACON_STACKSIZE]; + +uint8_t etx_send_buf[ETX_BUF_SIZE]; +uint8_t etx_rec_buf[ETX_BUF_SIZE]; + +//Message queue for radio +msg_t msg_q[ETX_RCV_BUFFER_SIZE]; + +//Transceiver command for sending ETX probes +transceiver_command_t tcmd; + +//Message to send probes with +msg_t mesg; + +static etx_probe_t * get_etx_send_buf(void) { + return ((etx_probe_t *) &(etx_send_buf[0])); +} +static etx_probe_t * get_etx_rec_buf(void) { + return ((etx_probe_t *) &(etx_rec_buf[0])); +} + +void init_etx_beaconing(void) { + + //set code + puts("INit of etx beaconing"); + etx_send_buf[0] = ETX_BEACON; + + etx_beacon_pid = thread_create(etx_beacon_buf, ETX_BEACON_STACKSIZE, + PRIORITY_MAIN - 1, CREATE_STACKTEST, + etx_beacon, "etx_beacon"); + + etx_radio_pid = thread_create(etx_radio_buf, ETX_BEACON_STACKSIZE, + PRIORITY_MAIN - 1, CREATE_STACKTEST, + etx_radio, "etx_radio"); + + //register at transceiver + transceiver_register(TRANSCEIVER_CC1100, etx_radio_pid); +} + +void etx_beacon(void) { + /* + * Sends a message every second +-10% jitter. + * A correcting variable keeps this timer from drifting off from the + * 1 second interval. + */ + radio_packet_t p; + + uint8_t test = 0; //TODO delete, change to true or sth. + uint8_t jittercorrection = 10; + uint8_t jitter = (uint8_t) (rand() % 21); + + while (test < 10) { + + //Prepare the ETX packet + mesg.type = SND_PKT; + mesg.content.ptr = (char*) &tcmd; + + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &p; + p.length = (get_etx_send_buf())->length + 2; //opt.+lngth+variable (addr,pkt_count) pairs + p.dst = 0; + p.data = (uint8_t *) &etx_send_buf; + msg_send(&mesg, transceiver_pid, 1); + + test++; + + hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); + + /* + * The jitter correction is needed to stay at a base interval of 1 sec. + * between the wakeups. It takes the old jittervalue in account and + * modifies the time to wait accordingly. + */ + jittercorrection = 20 - jitter; + + //the jitter is a number between 0 and 20 + jitter = (uint8_t) (rand() % 21); + + } +} + +void handle_etx_beacon(void) { + /* + * Handle the ETX probe that has been received and update all infos. + * For now, just print a nice output of what I got, so i see it works as + * intended. + */ + + etx_probe_t * probe = get_etx_rec_buf(); + + printf("ETX beacon package received with following values:\n" + "\tPackage Option:%x\n" + "\tPackage Length:%u\n\n", probe->code, probe->length); + + for (uint8_t i = 0; i < probe->length / 3; i++) { + printf("\tIPv6 Short Addr:%u%u\n" + "\tPackets f. Addr:%u\n\n", probe->data[i * 3], + probe->data[i * 3 + 1], probe->data[i * 3 + 2]); + } + +} + +void etx_radio(void) { + msg_t m; + radio_packet_t *p; + etx_probe_t *etx_pkt; + msg_init_queue(msg_q, ETX_RCV_BUFFER_SIZE); + + while (1) { + msg_receive(&m); + + if (m.type == PKT_PENDING) { + p = (radio_packet_t*) m.content.ptr; + etx_pkt = (etx_probe_t *) p->data; + + if (etx_pkt->code == ETX_BEACON) { + //copy to receive buffer + memcpy(etx_rec_buf, p->data, etx_pkt->length + 2); + handle_etx_beacon(); + } + p->processing--; + } + else if (m.type == ENOBUFFER) { + puts("Transceiver buffer full"); + } + else { + //packet is not for me + } + } +} diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h new file mode 100644 index 0000000000..861bda4efc --- /dev/null +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -0,0 +1,36 @@ +/* + * etx_beaconing.h + * + * Created on: Feb 26, 2013 + * Author: stephan + */ + +#ifndef ETX_BEACONING_H_ +#define ETX_BEACONING_H_ + +#include "rpl_structs.h" + +#define ETX_BEACON_STACKSIZE 2048 + +//[option|length|ipaddr.|packetcount] with up to 10 ipaddr|packetcount pairs +// 1 Byte 1 Byte 2 Byte 1 Byte +#define ETX_BUF_SIZE (32) + +#define ETX_RCV_BUFFER_SIZE (64) + +//ETX beaconing type (!ATTENTION! this is non-standard) +#define ETX_BEACON 0x20 + +//prototypes +void init_etx_beaconing(void); +void etx_beacon(void); +void etx_radio(void); + +typedef struct __attribute__((packed)) { + uint8_t code; + uint8_t length; + uint8_t* data; +} etx_probe_t; + + +#endif /* ETX_BEACONING_H_ */ From f5a59ab3197672dafb223dddbf49ceb7dacff1f9 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 12 Mar 2013 15:39:31 +0100 Subject: [PATCH 22/35] added a header file for rpl test project --- projects/test_rpl/main.h | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 projects/test_rpl/main.h diff --git a/projects/test_rpl/main.h b/projects/test_rpl/main.h new file mode 100644 index 0000000000..6b2134defe --- /dev/null +++ b/projects/test_rpl/main.h @@ -0,0 +1,11 @@ +/* + * main.h + * + * Created on: Mar 4, 2013 + * Author: stephan + */ + +#ifndef MAIN_H_ +#define MAIN_H_ + +#endif /* MAIN_H_ */ From adfc3306ab1078bfdf86c75c3f2f8a518e6e9918 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Fri, 15 Mar 2013 17:48:13 +0100 Subject: [PATCH 23/35] WARNING: BROKEN COMMIT added not working etx_beaconing into rpl, added small vtimer debug changes, changed cc1100 default mode --- drivers/cc110x/cc1100-interface.h | 5 +- projects/test_beacon/Jamfile | 5 + projects/test_beacon/main.c | 82 ++++++ projects/test_beacon/tests/hello-world | 13 + projects/test_ping/main.c | 2 - projects/test_rpl/main.c | 17 ++ sys/include/vtimer.h | 10 + sys/net/sixlowpan/rpl/Jamfile | 2 +- sys/net/sixlowpan/rpl/etx_beaconing.c | 331 ++++++++++++++++++++----- sys/net/sixlowpan/rpl/etx_beaconing.h | 40 ++- sys/net/sixlowpan/rpl/of0.c | 25 +- sys/net/sixlowpan/rpl/of0.h | 5 - sys/net/sixlowpan/rpl/of_mrhof.c | 230 ++++++++--------- sys/net/sixlowpan/rpl/of_mrhof.h | 56 ++--- sys/net/sixlowpan/rpl/rpl.c | 20 +- sys/net/sixlowpan/rpl/rpl.h | 2 + sys/net/sixlowpan/rpl/rpl_dodag.c | 15 +- sys/net/sixlowpan/rpl/rpl_dodag.h | 3 +- sys/net/sixlowpan/rpl/rpl_structs.h | 35 ++- sys/vtimer.c | 16 +- 20 files changed, 630 insertions(+), 284 deletions(-) create mode 100644 projects/test_beacon/Jamfile create mode 100644 projects/test_beacon/main.c create mode 100755 projects/test_beacon/tests/hello-world diff --git a/drivers/cc110x/cc1100-interface.h b/drivers/cc110x/cc1100-interface.h index ff9a0f2d5e..e097c422e3 100644 --- a/drivers/cc110x/cc1100-interface.h +++ b/drivers/cc110x/cc1100-interface.h @@ -66,7 +66,10 @@ and the mailinglist (subscription via web site) // Define default radio mode to constant RX if no // project specific setting is available. #ifndef CC1100_RADIO_MODE - #define CC1100_RADIO_MODE CC1100_MODE_CONSTANT_RX + /* TODO define this to be CC1100_MODE_CONSTANT_RX again and + * put the CC1100_MODE_WOR definition into the RPL specific project + */ + #define CC1100_RADIO_MODE CC1100_MODE_WOR #endif /// CC1100 radio interface diff --git a/projects/test_beacon/Jamfile b/projects/test_beacon/Jamfile new file mode 100644 index 0000000000..1b244cb4f2 --- /dev/null +++ b/projects/test_beacon/Jamfile @@ -0,0 +1,5 @@ +SubDir TOP projects test_beacon ; + +Module test_beacon : main.c : shell shell_commands ps posix_io uart0 auto_init vtimer 6lowpan uart0 posix_io cc110x rpl ; + +UseModule test_beacon ; diff --git a/projects/test_beacon/main.c b/projects/test_beacon/main.c new file mode 100644 index 0000000000..66c48be18c --- /dev/null +++ b/projects/test_beacon/main.c @@ -0,0 +1,82 @@ +#include +#include +#include +#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/etx_beaconing.h" + +ipv6_addr_t my_address = { 0 }; + +void init(char *str){ + transceiver_command_t tcmd; + msg_t m; + uint8_t chan = 10; + + uint16_t r_addr; + + int res = sscanf(str, "init %hu", &r_addr); + + if(res < 1){ + printf("Usage: init address\n"); + printf("\taddress must be an 8 bit integer\n"); + return; + } + + printf("INFO: Initialize on address %d\n", r_addr); + if (r_addr > 255) { + printf("ERROR: address not an 8 bit integer\n"); + return; + } + + sixlowpan_init(TRANSCEIVER_CC1100,r_addr,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 channel to 10 */ + tcmd.transceivers = TRANSCEIVER_CC1100; + tcmd.data = &chan; + m.type = SET_CHANNEL; + m.content.ptr = (void*) &tcmd; + + msg_send_receive(&m, &m, transceiver_pid); + + etx_init_beaconing(&my_address); +} + +void table(char *str){ + thread_print_all(); +} + +const shell_command_t shell_commands[] = { + {"init", "", init}, + {"table", "", table}, + {NULL, NULL, NULL} +}; + +int main(void) { + printf("ETX Test Application\n"); + + + posix_open(uart0_handler_pid, 0); + + shell_t shell; + shell_init(&shell, shell_commands, uart0_readc, uart0_putc); + + shell_run(&shell); + + return 0; +} diff --git a/projects/test_beacon/tests/hello-world b/projects/test_beacon/tests/hello-world new file mode 100755 index 0000000000..acde8265fe --- /dev/null +++ b/projects/test_beacon/tests/hello-world @@ -0,0 +1,13 @@ +#!/usr/bin/expect + +set timeout 5 + +spawn pseudoterm $env(PORT) + +expect { + "Hello World!" {} + timeout { exit 1 } +} + +puts "\nTest successful!\n" + diff --git a/projects/test_ping/main.c b/projects/test_ping/main.c index 5dbc94fdc8..a7756ccc90 100644 --- a/projects/test_ping/main.c +++ b/projects/test_ping/main.c @@ -32,8 +32,6 @@ char stack_shell[SHELL_STACK]; char stack_radio[RADIO_STACK]; -uint8_t snd_buffer[SND_BUFFER_SIZE][CC1100_MAX_DATA_LENGTH]; - msg_t msg_q[RCV_BUFFER_SIZE]; transceiver_command_t tcmd; diff --git a/projects/test_rpl/main.c b/projects/test_rpl/main.c index adbb809d05..dc1e4823a3 100644 --- a/projects/test_rpl/main.c +++ b/projects/test_rpl/main.c @@ -1,3 +1,4 @@ +#include "main.h" #include #include #include @@ -143,6 +144,7 @@ void table(char *str){ } } printf("$\n"); + thread_print_all(); } void dodag(char *str){ @@ -175,6 +177,20 @@ void wakeup(char* unused) { thread_wakeup(10); } +void send_msg(char* message) { + rpl_dodag_t * my_dodag = rpl_get_my_dodag(); + ipv6_addr_t rootid = my_dodag->dodag_id; + ipv6_addr_t* next_hop = rpl_get_next_hop(&rootid); + //TODO implement + //if(my_dodag->node_status == ROOT_NODE){ + //don't send when root + // puts("[ERROR] I'm root, please send from another node."); + // return; + //} + + //rpl_send(&next_hop,message,length,next_header,NULL); +} + const shell_command_t shell_commands[] = { {"init", "", init}, {"table", "", table}, @@ -182,6 +198,7 @@ const shell_command_t shell_commands[] = { {"cc1100", "", cc1100_cfg}, {"wakeup", "", wakeup}, {"loop", "", loop}, + {"send", "", send_msg}, {NULL, NULL, NULL} }; diff --git a/sys/include/vtimer.h b/sys/include/vtimer.h index 2a5d7a0d97..5735607f4e 100644 --- a/sys/include/vtimer.h +++ b/sys/include/vtimer.h @@ -91,4 +91,14 @@ int vtimer_set_wakeup(vtimer_t *t, timex_t interval, int pid); */ int vtimer_remove(vtimer_t *t); +/** + * @brief Prints the vtimer shortterm queue (use for debug purposes) + */ +void vtimer_print_short_queue(); + +/** + * @brief Prints the vtimer longterm queue (use for debug purposes) + */ +void vtimer_print_long_queue(); + #endif /* __VTIMER_H */ diff --git a/sys/net/sixlowpan/rpl/Jamfile b/sys/net/sixlowpan/rpl/Jamfile index 738beef80e..512a95776f 100644 --- a/sys/net/sixlowpan/rpl/Jamfile +++ b/sys/net/sixlowpan/rpl/Jamfile @@ -1,3 +1,3 @@ SubDir TOP sys net sixlowpan rpl ; -Module rpl : rpl.c of0.c rpl_dodag.c trickle.c : vtimer ; +Module rpl : rpl.c of0.c of_mrhof.c rpl_dodag.c trickle.c etx_beaconing.c : vtimer hwtimer ; diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index 0c216e030d..1386075059 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -11,23 +11,51 @@ #include #include +#include #include #include +#include "sys/net/sixlowpan/sixlowmac.h" +#include "sys/net/sixlowpan/ieee802154_frame.h" +#include "rpl_structs.h" +#include "rpl_dodag.h" + #define MS 10000 -unsigned int etx_beacon_pid; -unsigned int etx_radio_pid; +int etx_beacon_pid = 0; +int etx_radio_pid = 0; +int etx_update_pid = 0; //Buffer -char etx_beacon_buf[ETX_BEACON_STACKSIZE]; -char etx_radio_buf[ETX_BEACON_STACKSIZE]; +char etx_beacon_buf[ETX_BEACON_STACKSIZE] = { 0 }; +char etx_radio_buf[ETX_RADIO_STACKSIZE] = { 0 }; +char etx_update_buf[ETX_UPDT_STACKSIZE] = { 0 }; -uint8_t etx_send_buf[ETX_BUF_SIZE]; -uint8_t etx_rec_buf[ETX_BUF_SIZE]; +uint8_t etx_send_buf[ETX_BUF_SIZE] = { 0 }; +uint8_t etx_rec_buf[ETX_BUF_SIZE] = { 0 }; + +/* + * The counter for the current 'round'. An ETX beacon is sent every ETX_INTERVAL + * u-seconds and a node computes the ETX value by comparing the the received + * probes vs the expected probes from a neighbor every ETX_ROUND intervals. + */ +static uint8_t rounds = 0; //Message queue for radio -msg_t msg_q[ETX_RCV_BUFFER_SIZE]; +msg_t msg_que[ETX_RCV_BUFFER_SIZE] = { 0 }; + +/* + * This could (and should) be done differently, once the RPL implementation + * deals with candidate neighbors in another way than just defining that every + * possible neighbor we hear from is a parent. + * Right now, we need to keep track of the ETX values of other nodes without + * needing them to be in our parent array, so we have another array here in + * which we put all necessary info for up to RPL_MAX_CANDIDATE_NEIGHBORS + * candidates. + */ +//Candidate array for candidate<==>parent matching +//Throws a warning, but this is the correct way to initialize! +static rpl_candidate_neighbor_t candidates[RPL_MAX_CANDIDATE_NEIGHBORS] = { 0 }; //Transceiver command for sending ETX probes transceiver_command_t tcmd; @@ -35,6 +63,9 @@ transceiver_command_t tcmd; //Message to send probes with msg_t mesg; +//RPL-address +static ipv6_addr_t * own_address; + static etx_probe_t * get_etx_send_buf(void) { return ((etx_probe_t *) &(etx_send_buf[0])); } @@ -42,83 +73,218 @@ static etx_probe_t * get_etx_rec_buf(void) { return ((etx_probe_t *) &(etx_rec_buf[0])); } -void init_etx_beaconing(void) { +//TODO delete +void etx_beacon2(void); +void show_candidates(void) { + //TODO delete + /* + for (int i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + printf("Candidates Addr:%d\n" + "\t cur_etx:%f\n" + "\t packets_rx:%d\n" + "\t used:%d\n", candidates[i].addr.uint8[15], + candidates[i].cur_etx, candidates[i].packets_rx, + candidates[i].used); + } + */ + rpl_candidate_neighbor_t * candidate; + rpl_candidate_neighbor_t *end; - //set code - puts("INit of etx beaconing"); + for (candidate = &candidates[0], end = candidates + + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; + candidate++) { + printf("Candidates Addr:%d\n" + "\t cur_etx:%f\n" + "\t packets_rx:%d\n" + "\t used:%d\n", candidate->addr.uint8[15], + candidate->cur_etx, candidate->packets_rx, + candidate->used); + } +} + +void etx_init_beaconing(ipv6_addr_t * address) { + own_address = address; + show_candidates(); +//set code + printf("ETX BEACON INIT"); etx_send_buf[0] = ETX_BEACON; - etx_beacon_pid = thread_create(etx_beacon_buf, ETX_BEACON_STACKSIZE, - PRIORITY_MAIN - 1, CREATE_STACKTEST, - etx_beacon, "etx_beacon"); + thread_print_all(); + // etx_beacon_pid = thread_create(etx_beacon_buf, ETX_BEACON_STACKSIZE, + // PRIORITY_MAIN - 1, CREATE_STACKTEST, + // etx_beacon2, "etx_beacon"); - etx_radio_pid = thread_create(etx_radio_buf, ETX_BEACON_STACKSIZE, + etx_radio_pid = thread_create(etx_radio_buf, ETX_RADIO_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, etx_radio, "etx_radio"); - //register at transceiver + printf("etx radio pid is %d", etx_radio_pid); + /* + * Maybe this should not be in a seperate thread resource-wise, but the + * motive was to delay beacon-sending as little as possible, as this would + * derail beaconing from the intended ETX_INTERVAL. + */ + + //TODO delete + show_candidates(); + + etx_update_pid = thread_create(etx_update_buf, ETX_UPDT_STACKSIZE, + PRIORITY_MAIN - 1, CREATE_STACKTEST, + etx_update, "etx_update"); + + //TODO delete + show_candidates(); + + //TODO delete + thread_wakeup(etx_update_pid); + +//register at transceiver transceiver_register(TRANSCEIVER_CC1100, etx_radio_pid); + printf("...[DONE]\n"); +} + +void etx_beacon2(void) { +//TODO delete or delete beacon, whatever do use 1 method and del the other + etx_probe_t *etx_p = get_etx_send_buf(); + + ieee_802154_long_t empty_addr = { 0 }; + + uint8_t jittercorrection = 10; + uint8_t jitter = (uint8_t) (rand() % 21); + uint8_t p_length = 0; + + while (true) { + if (rounds == ETX_ROUNDS) { + //calculate the ETX values and update the parents + thread_wakeup(etx_update_pid); + rounds = 1; + } else { + rounds++; + } + + vtimer_usleep(80 * MS + jittercorrection * MS + jitter * MS); + /// TODO once vtimer works as intended, replace the hwtimer here with + /// the vtimer. Right now vtimer bugs, so we have hwtimer here. + //hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); + + jittercorrection = 20 - jitter; + + //the jitter is a value between 0 and 20 + jitter = (uint8_t) (rand() % 21); + printf("jitter: %d", jitter); + puts("beacon2 run through complete"); + show_candidates(); + } } void etx_beacon(void) { /* - * Sends a message every second +-10% jitter. - * A correcting variable keeps this timer from drifting off from the - * 1 second interval. + * TODO use ETX_INTERVAL variable instead of fixed value + * Sends a message every ETX_INTERVAL +/- a small jitter-value. + * A correcting variable is needed to stay at a base interval of + * ETX_INTERVAL between the wakeups. It takes the old jittervalue in account + * and modifies the time to wait accordingly. */ - radio_packet_t p; - - uint8_t test = 0; //TODO delete, change to true or sth. + etx_probe_t *etx_p = get_etx_send_buf(); uint8_t jittercorrection = 10; uint8_t jitter = (uint8_t) (rand() % 21); - while (test < 10) { + uint8_t p_length = 0; - //Prepare the ETX packet - mesg.type = SND_PKT; - mesg.content.ptr = (char*) &tcmd; + ieee_802154_long_t empty_addr = { 0 }; - tcmd.transceivers = TRANSCEIVER_CC1100; - tcmd.data = &p; - p.length = (get_etx_send_buf())->length + 2; //opt.+lngth+variable (addr,pkt_count) pairs - p.dst = 0; - p.data = (uint8_t *) &etx_send_buf; - msg_send(&mesg, transceiver_pid, 1); + while (true) { - test++; + if (rounds == ETX_ROUNDS) { + //calculate the ETX values and update the parents + thread_wakeup(etx_update_pid); + rounds = 1; + } else { + rounds++; + } - hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); + //Build etx packet + p_length = 0; + for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + if (candidates[i].used != 0) { + etx_p->data[i * 2] = candidates[i].addr.uint8[15]; + etx_p->data[i * 2 + 1] = candidates[i].packets_rx; + p_length = p_length + 2; + } + } + etx_p->length = p_length; + + send_ieee802154_frame(&empty_addr, &etx_send_buf[0], + get_etx_send_buf()->length + 2, 1); + puts("sent beacon!"); + //hwtimer buggt noch mehr als der vtimer... + vtimer_usleep(80 * MS + jittercorrection * MS + jitter * MS); + /// TODO once vtimer works as intended, replace the hwtimer here with + /// the vtimer. Right now vtimer bugs, so we have hwtimer here. + //hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); - /* - * The jitter correction is needed to stay at a base interval of 1 sec. - * between the wakeups. It takes the old jittervalue in account and - * modifies the time to wait accordingly. - */ jittercorrection = 20 - jitter; - //the jitter is a number between 0 and 20 + //the jitter is a value between 0 and 20 jitter = (uint8_t) (rand() % 21); - + printf("jitter: %d", jitter); } } -void handle_etx_beacon(void) { +rpl_candidate_neighbor_t * etx_find_candidate(ipv6_addr_t * address) { + /* + * find the candidate with address address and returns it, or returns NULL + * if no candidate having this address was found. + */ + //for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + // if (candidates[i].used + // && (rpl_equal_id(&candidates[i].addr, address))) { + // return &candidates[i]; + // } + //} + return NULL ; +} + +double etx_get_metric(ipv6_addr_t * address) { + rpl_candidate_neighbor_t * candidate = etx_find_candidate(address); + if (candidate != NULL ) { + return candidate->packets_rx / (double) ETX_ROUNDS; + } + return 0; +} + +void etx_handle_beacon(ipv6_addr_t * candidate_address) { + puts("handle_beacon"); //TODO del /* * Handle the ETX probe that has been received and update all infos. - * For now, just print a nice output of what I got, so i see it works as - * intended. */ etx_probe_t * probe = get_etx_rec_buf(); +//Todo delete once everything works well printf("ETX beacon package received with following values:\n" "\tPackage Option:%x\n" - "\tPackage Length:%u\n\n", probe->code, probe->length); + "\t Data Length:%u\n" + "\tSource Address:%d\n\n", probe->code, probe->length, + candidate_address->uint8[15]); - for (uint8_t i = 0; i < probe->length / 3; i++) { - printf("\tIPv6 Short Addr:%u%u\n" - "\tPackets f. Addr:%u\n\n", probe->data[i * 3], - probe->data[i * 3 + 1], probe->data[i * 3 + 2]); + rpl_candidate_neighbor_t* candidate = NULL; + + for (uint8_t i = 0; i < probe->length / 2; i++) { + //todo delete once everything works well + printf("\tIPv6 short Addr:%u\n" + "\tPackets f. Addr:%u\n\n", probe->data[i * 2], + probe->data[i * 2 + 1]); + + // If i find my address in this probe, update the packet_rx value for + // this candidate, if he is in my candidate list. + if (probe->data[i * 2] == own_address->uint8[15]) { + //candidate = etx_find_candidate(candidate_address); + candidate = NULL; + if (candidate != NULL ) { + candidate->packets_rx = probe->data[i * 2 + 1]; + } + } } } @@ -126,28 +292,81 @@ void handle_etx_beacon(void) { void etx_radio(void) { msg_t m; radio_packet_t *p; - etx_probe_t *etx_pkt; - msg_init_queue(msg_q, ETX_RCV_BUFFER_SIZE); + + ieee802154_frame_t frame; + + msg_init_queue(msg_que, ETX_RCV_BUFFER_SIZE); + +// ipv6_addr_t ll_address; +// ipv6_addr_t candidate_addr; + +// ipv6_set_ll_prefix(&ll_address); +// ipv6_get_saddr(&candidate_addr, &ll_address); while (1) { + puts("radio"); //TODO del msg_receive(&m); - + puts("msg received"); if (m.type == PKT_PENDING) { p = (radio_packet_t*) m.content.ptr; - etx_pkt = (etx_probe_t *) p->data; - if (etx_pkt->code == ETX_BEACON) { + read_802154_frame(p->data, &frame, p->length); + + if (frame.payload[0] == ETX_BEACON) { //copy to receive buffer - memcpy(etx_rec_buf, p->data, etx_pkt->length + 2); - handle_etx_beacon(); + memcpy(etx_rec_buf, &frame.payload[0], frame.payload_len); + + //create IPv6 address from radio packet + //we can do the cast here since rpl nodes can only have addr + //up to 8 bits + // candidate_addr.uint8[15] = (uint8_t) p->src; + //handle the beacon + // etx_handle_beacon(&candidate_addr); + etx_handle_beacon(0); } + p->processing--; } else if (m.type == ENOBUFFER) { puts("Transceiver buffer full"); } else { - //packet is not for me + //packet is not for me, whatever + } + } +} + +void etx_update(void) { + /* + * Update the current ETX values, then + * reset the received packet count for the candidates. + * + * This thread should never take very long, as it has to be done in less + * than (ETX_INTERVAL - maximum jitter), otherwise the ETX calculation might + * be faulty. TODO delete this once mutexes are in place + * + */ + rpl_candidate_neighbor_t * candidate; + rpl_candidate_neighbor_t *end; + + while (true) { + //good night + thread_sleep(); + //Wait a tiny bit to allow for the last packet to be processed + hwtimer_wait(HWTIMER_TICKS(200)); + + for (candidate = &candidates[0], end = candidates + + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; + candidate++) { + + if (candidate->used != 0) { + //update its ETX-metric and packet count TODO mutex this + candidate->cur_etx = candidate->packets_rx / (double) 10; + candidate->packets_rx = 0; + printf( + "Updated ETX Metric to %f for candidate used was on %d", + candidate->cur_etx, candidate->used); + } } } } diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index 861bda4efc..96b0f9815d 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -1,4 +1,5 @@ /* + * Header for the ETX-beaconing module * etx_beaconing.h * * Created on: Feb 26, 2013 @@ -8,24 +9,51 @@ #ifndef ETX_BEACONING_H_ #define ETX_BEACONING_H_ -#include "rpl_structs.h" +#include "sys/net/sixlowpan/sixlowip.h" -#define ETX_BEACON_STACKSIZE 2048 +#define ETX_BEACON_STACKSIZE 1024 +#define ETX_RADIO_STACKSIZE 1024 +#define ETX_UPDT_STACKSIZE 256 +#define ETX_INTERVAL 1000000 //1 Second in us is the default value +#define ETX_ROUNDS 10 //10 is the default value -//[option|length|ipaddr.|packetcount] with up to 10 ipaddr|packetcount pairs -// 1 Byte 1 Byte 2 Byte 1 Byte +//[option|length|ipaddr.|packetcount] with up to 15 ipaddr|packetcount pairs +// 1 Byte 1 Byte 1 Byte 1 Byte #define ETX_BUF_SIZE (32) -#define ETX_RCV_BUFFER_SIZE (64) +#define ETX_RCV_BUFFER_SIZE (128) //ETX beaconing type (!ATTENTION! this is non-standard) #define ETX_BEACON 0x20 //prototypes -void init_etx_beaconing(void); +void etx_init_beaconing(ipv6_addr_t * address); void etx_beacon(void); +double etx_get_metric(ipv6_addr_t * address); +void etx_update(void); void etx_radio(void); +/* + * The ETX beaconing packet consists of: + * + * 0 1 2 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - + * | Option Type | Option Length | Data + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - + * Option type: Set to 0x20 + * + * Option Length: The length of the Data sent with this packet + * + * Option Data: 2-Octet Pairs of 8 bit for addresses and a positive integer + * denoting the amount of packets received from that IP address + * + * We only need 1 octet for the ip address since RPL for now only allows for + * 255 different addresses. + * + * If the length of this packet says 0, it has received no other beaconing + * packets itself so far. + */ typedef struct __attribute__((packed)) { uint8_t code; uint8_t length; diff --git a/sys/net/sixlowpan/rpl/of0.c b/sys/net/sixlowpan/rpl/of0.c index 815a618379..dc193a9c48 100644 --- a/sys/net/sixlowpan/rpl/of0.c +++ b/sys/net/sixlowpan/rpl/of0.c @@ -1,14 +1,18 @@ #include #include "of0.h" +//Function Prototypes +static uint16_t calc_rank(rpl_parent_t *, uint16_t); +static rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); +static rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *); +static void reset(rpl_dodag_t *); + rpl_of_t rpl_of0 = { 0x0, calc_rank, which_parent, which_dodag, reset, - NULL, - NULL, NULL }; @@ -20,19 +24,12 @@ void reset(rpl_dodag_t *dodag){ //Nothing to do in OF0 } -uint16_t calc_rank(){ - rpl_parent_t * parent = rpl_find_preferred_parent(); - uint16_t my_rank = rpl_get_my_dodag()->my_rank; - - if(i_am_root){ - return rpl_get_my_dodag()->minhoprankincrease; - } - - if(my_rank == 0) { +uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank){ + if(base_rank == 0) { if(parent == NULL) { return INFINITE_RANK; } - my_rank = parent->rank; + base_rank = parent->rank; } uint16_t add; @@ -42,10 +39,10 @@ uint16_t calc_rank(){ else{ add = DEFAULT_MIN_HOP_RANK_INCREASE; } - if( my_rank + add < my_rank ){ + if( base_rank + add < base_rank ){ return INFINITE_RANK; } - return my_rank + add; + return base_rank + add; } //We simply return the Parent with lower rank diff --git a/sys/net/sixlowpan/rpl/of0.h b/sys/net/sixlowpan/rpl/of0.h index 2d3029039f..443d305564 100644 --- a/sys/net/sixlowpan/rpl/of0.h +++ b/sys/net/sixlowpan/rpl/of0.h @@ -1,8 +1,3 @@ #include "rpl_structs.h" rpl_of_t *rpl_get_of0(); -uint16_t calc_rank(); -rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); -rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *); -void reset(rpl_dodag_t *); - diff --git a/sys/net/sixlowpan/rpl/of_mrhof.c b/sys/net/sixlowpan/rpl/of_mrhof.c index 91b5978cf4..c76082c892 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.c +++ b/sys/net/sixlowpan/rpl/of_mrhof.c @@ -1,11 +1,16 @@ #include -#include +#include #include "of_mrhof.h" -static char is_initialised = 0; +// Function Prototypes +static uint16_t calc_rank(rpl_parent_t *, uint16_t); +static rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); +static rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *); +static void reset(rpl_dodag_t *); +static uint16_t calc_path_cost(rpl_parent_t * parent); uint16_t cur_min_path_cost = MAX_PATH_COST; -static mrhof_candidate_info_t candidate_info[RPL_MAX_CANDIDATE_NEIGHBORS]; +rpl_parent_t * cur_preferred_parent = NULL; rpl_of_t rpl_of_mrhof = { 0x1, @@ -13,170 +18,137 @@ rpl_of_t rpl_of_mrhof = { which_parent, which_dodag, reset, - init, NULL -}; + }; -rpl_of_t *rpl_get_of_mrhof() { +rpl_of_t * rpl_get_of_mrhof(void) { return &rpl_of_mrhof; } -void init() { - //TODO implement OF-specific init of timers/functions/structs/whatever - if (!is_initialised) { - //blabla init this node - } - is_initialised = 1; -} - void reset(rpl_dodag_t *dodag) { - //todo implement if necessary } -void calc_path_cost() { +static uint16_t calc_path_cost(rpl_parent_t * parent) { /* - * Calculates the path cost through all candidate neighbours and sets - * cur_min_path_cost to the lowest value? + * Calculates the path cost through the parent, for now, only for ETX */ - - if(i_am_root){ - //Since for now we only support ETX, the pastcost that computes to - //a rank of minhoprankincrease IS minhoprankincrease - cur_min_path_cost = rpl_get_my_dodag()->minhoprankincrease; - return; + if (parent == NULL ) { + // Shouldn't ever happen since this function is supposed to be always + // run with a parent. If it does happen, we can assume a root called it. + printf("[WARNING] calc_path_cost called without parent!"); + return DEFAULT_MIN_HOP_RANK_INCREASE; } - /* - * This is the boolean describing if I need to do a parent selection. - * This happens always when the past cost for a candidate neighbor OR a - * parent changes. - */ - char do_parent_selection = 0; - uint16_t path_cost = 0; - for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { - if(candidates[i].used){ - if(candidate_info[i].cur_etx != 0){ - /* The RFC specifies this computation a bit ambiguously, this is - * what I understood: - * - * (ETX_for_link_to_neighbor * 128) + Rank_of_that_neighbor - * - * This means I get the rank of that neighbor (which is the etx - * of the whole path from him to the root node) plus my ETX to - * that neighbor*128, which would be the 'rank' of the single link - * from me to that neighbor - * - */ - path_cost = candidate_info[i].cur_etx*ETX_RANK_MULTIPLIER + (candidates[i].dodag->my_rank); - if(candidate_info[i].cur_path_cost == path_cost){ - //nothing changed - continue; - } - do_parent_selection = 1; - candidate_info[i].cur_path_cost = path_cost; - }else{ - //if it is 0, the value has not been computed yet, so we can't - //compute a path cost - if(candidate_info[i].cur_path_cost == MAX_PATH_COST){ - //nothing changed - continue; - } - do_parent_selection = 1; - candidate_info[i].cur_path_cost = MAX_PATH_COST; - } + double etx_value = etx_get_metric(parent->addr); + if (etx_value != 0) { + /* + * (ETX_for_link_to_neighbor * 128) + Rank_of_that_neighbor + * + * This means I get the rank of that neighbor (which is the etx + * of the whole path from him to the root node) plus my ETX to + * that neighbor*128, which would be the 'rank' of the single link + * from me to that neighbor + * + */ + if (etx_value * ETX_RANK_MULTIPLIER > MAX_LINK_METRIC) { + // Disallow links with an estimated ETX of 4 or higher + return MAX_PATH_COST; } - } - if(do_parent_selection){ - parent_selection(); - } + if (etx_value * ETX_RANK_MULTIPLIER + parent->rank + < parent->rank) { + //Overflow + return MAX_PATH_COST; + } + //TODO runden + return etx_value * ETX_RANK_MULTIPLIER + + parent->rank; + } else { + // IMPLEMENT HANDLING OF OTHER METRICS HERE + // if it is 0, it hasn't been computed, thus we cannot compute a path + // cost + return MAX_PATH_COST; + } } -uint16_t calc_rank() { +static uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank) { /* - * Return the rank for this node (calculated from path cost). - * There will be 3 values calculated, the highest of those 3 values will be - * used as the noderank. + * Return the rank for this node. * * For now, there is no metric-selection or specification, so the rank com- * putation will always be assumed to be done for the ETX metric. + * Baserank is pretty much only used to find out if a node is a root or not. */ - uint16_t result = INFINITE_RANK; + if (parent == NULL ) { + if (base_rank == 0) { + //No parent, no rank, a root node would have a rank != 0 + return INFINITE_RANK; + } - //Holds the 3 computed values for the nodes rank from which the max value - //will be the nodes actual rank - uint16_t rankarray[3] = {0,0,0}; + /* + * No parent, base_rank != 0 means this is a root node or a node which + * is recalculating. + * Since a recalculating node must have a parent in this implementation + * (see rpl.c, function global_repair), we can assume this node is root. + */ + return DEFAULT_MIN_HOP_RANK_INCREASE; + } else { + /* + * We have a parent and are a non-root node, calculate the path cost for + * the parent and choose the maximum of that value and the advertised + * rank of the parent + minhoprankincrease for our rank. + */ + uint16_t calculated_pcost = calc_path_cost(parent); - //TODO finish this - //rankarray[0] = (rpl_find_preferred_parent()->rank > ; - - if (i_am_root) { - result = rpl_get_my_dodag()->minhoprankincrease; - return result; - } - - //Check which parent has the highest advertised rank - for (uint8_t i = 0; i < RPL_MAX_PARENTS; i++) { - if (parents[i].used) { - if (parents[i].rank == INFINITE_RANK){ - // parent not useful, should be deleted //TODO check if deletion - // should be triggered from here - continue; - } - else if (parents[i].rank > rankarray[2]) { - //store it away - rankarray[2] = parents[i].rank; + if (calculated_pcost < MAX_PATH_COST) { + if ((parent->rank + parent->dodag->minhoprankincrease) + > calculated_pcost) { + return parent->rank + parent->dodag->minhoprankincrease; + } else { + return calculated_pcost; } + } else { + //Path costs are greater than allowed + return INFINITE_RANK; } } - - //Compute 2nd rankvalue and store it in 2nd place in the array - if(rpl_get_my_dodag()->minhoprankincrease * (1 + (rankarray[2]/rpl_get_my_dodag()->minhoprankincrease)) < rankarray[2]){ - //overflow - rankarray[1] = INFINITE_RANK; - }else{ - rankarray[1] = rpl_get_my_dodag()->minhoprankincrease * (1 + (rankarray[2]/rpl_get_my_dodag()->minhoprankincrease)); - } - - //Compute the 3rd rankvalue and store it in the 3rd place - if(rankarray[2] - rpl_get_my_dodag()->maxrankincrease ) - - - return result; } -void parent_selection(){ +static rpl_parent_t * which_parent(rpl_parent_t * p1, rpl_parent_t * p2) { /* - * Select a candidate neighbor as preferred parent. + * Return the parent with the lowest path cost. + * Before returning any of the two given parents, make sure that a switch is + * desirable. * - * Note: - * If we allow floating roots, a node may have no parents */ + uint16_t path_p1 = calc_path_cost(p1); + uint16_t path_p2 = calc_path_cost(p2); - /* - * Might be faster to set the node directly? - */ - uint8_t cur_min_path_neighbor_index = 0; - uint16_t min_path_cost = MAX_PATH_COST; - - for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { - /* - * Go through all Candidate Neighbors, compare their path cost with cur- - * rent minimum path cost and change cur_min_path_neighbor_index - * to the index of the current neighbor if his path is 'shorter' - */ - if(candidates[i].used && (candidate_info[i].cur_path_cost < MAX_LINK_METRIC)){ - if(candidate_info[i].cur_path_cost < min_path_cost){ - cur_min_path_neighbor_index = i; + if(cur_preferred_parent != NULL){ + //test if the parent from which we got this path is still active + if(cur_preferred_parent->used != 0){ + // Test, if the current best path is better than both parents given + if(cur_min_path_cost < path_p1 + PARENT_SWITCH_THRESHOLD + && cur_min_path_cost < path_p2 + PARENT_SWITCH_THRESHOLD){ + return cur_preferred_parent; } } } - //TODO finish this. - //rpl_find_preferred_parent() + if (path_p1 < path_p2) { + /* + * Return the current best parent, and set it as current best parent + */ + cur_min_path_cost = path_p1; + cur_preferred_parent = p1; + return p1; + } + cur_min_path_cost = path_p2; + cur_preferred_parent = p2; + return p2; } //Not used yet, as the implementation only makes use of one dodag for now. -rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2) { +static rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2) { return d1; } diff --git a/sys/net/sixlowpan/rpl/of_mrhof.h b/sys/net/sixlowpan/rpl/of_mrhof.h index ed4aa04377..b15f31e855 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.h +++ b/sys/net/sixlowpan/rpl/of_mrhof.h @@ -1,47 +1,35 @@ #include "rpl_structs.h" -// Disallow links with greater than 4 expected -// transmission counts on the selected path. +/* + * Disallow links with greater than 4 expected + * transmission counts on the selected path. + */ #define MAX_LINK_METRIC (512) -// Disallow paths with greater than 256 -// expected transmission counts. +/* + * Disallow paths with greater than 256 + * expected transmission counts. + */ #define MAX_PATH_COST (0x8000) -// Switch to a new path only if it is -// expected to require at least 1.5 fewer transmissions than the -// current path. +/* + * Switch to a new path only if it is + * expected to require at least 1.5 fewer transmissions than the + * current path. + */ #define PARENT_SWITCH_THRESHOLD (192) -// If the preferred parent is not available, some more -// candidate parents are still available without triggering a new -// round of route discovery. -#define PARENT_SET_SIZE (RPL_MAX_PARENTS) - -// Do not allow a node to become a floating root. +/* + * Do not allow a node to become a floating root. + * (Currently unused, since the RPL-implementation does not allow for floating + * roots). + */ #define ALLOW_FLOATING_ROOT (0) -// While assigning Rank when using ETX, use the representation of ETX described -// in [RFC6551], i.e., assign Rank equal to ETX * 128. +/* + * While assigning Rank when using ETX, use the representation of ETX described + * in [RFC6551], i.e., assign Rank equal to ETX * 128. + */ #define ETX_RANK_MULTIPLIER (0x80) rpl_of_t *rpl_get_of_mrhof(); -uint16_t calc_rank(); -uint16_t calc_path_cost(); -uint16_t calc_etx_value(); -rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); -rpl_dodag_t *which_dodag(rpl_dodag_t *, rpl_dodag_t *); -void reset(rpl_dodag_t *); - -//############################ -// OF specific structs ####### -//############################ - -//neighbour struct for etx path calculation -typedef struct mrhof_candidate_info_t { - ipv6_addr_t addr; - uint16_t packet_snt; - uint16_t packet_rec; - uint16_t cur_path_cost; - uint16_t cur_etx; -} mrhof_candidate_info_t; diff --git a/sys/net/sixlowpan/rpl/rpl.c b/sys/net/sixlowpan/rpl/rpl.c index c2c76f1ec3..9671a37ee6 100644 --- a/sys/net/sixlowpan/rpl/rpl.c +++ b/sys/net/sixlowpan/rpl/rpl.c @@ -4,7 +4,9 @@ #include #include "msg.h" #include "rpl.h" +#include "etx_beaconing.h" #include "of0.h" +#include "of_mrhof.h" #include "trickle.h" #include "sys/net/sixlowpan/sixlowmac.h" @@ -165,6 +167,12 @@ uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address){ ipv6_get_saddr(&my_address, &ll_address); set_rpl_process_pid(rpl_process_pid); + //Initialize ETX-calculation if needed + if(RPL_DEFAULT_OCP == 1){ + puts("INIT ETX BEACONING"); + etx_init_beaconing(&my_address); + } + return SUCCESS; } @@ -197,15 +205,10 @@ void rpl_init_root(){ dodag->lifetime_unit = RPL_LIFETIME_UNIT; dodag->version = RPL_COUNTER_INIT; dodag->grounded = RPL_GROUNDED; + dodag->node_status = (uint8_t) ROOT_NODE; dodag->my_rank = ROOT_RANK; //TODO change this, according to spec. dodag->joined = 1; dodag->my_preferred_parent = NULL; - - //OF-specific initialisation, if needed. - //For non-root nodes, this happens when a DIO with a OF is received - if(dodag->of->init != NULL){ - dodag->of->init(); - } } else{ printf("Error - could not generate DODAG\n"); @@ -515,7 +518,6 @@ void recv_rpl_dio(void){ break; } case(RPL_OPT_DAG_METRIC_CONTAINER):{ - //TODO implement handling of Metric container len += rpl_opt_buf->length +2; break; } @@ -625,10 +627,6 @@ void recv_rpl_dio(void){ // // Parent Handling // - - //TODO parent selection should not be run from RPL core but from the object- - //ive function, the parents set here should be instead the candidate neigh- - //bor set // //Ist Knoten bereits Parent? rpl_parent_t *parent; diff --git a/sys/net/sixlowpan/rpl/rpl.h b/sys/net/sixlowpan/rpl/rpl.h index 698a1fb9d7..076f2b9c40 100644 --- a/sys/net/sixlowpan/rpl/rpl.h +++ b/sys/net/sixlowpan/rpl/rpl.h @@ -5,6 +5,8 @@ #include "sys/net/sixlowpan/sixlowip.h" #include "rpl_dodag.h" +#define CC1100_RADIO_MODE CC1100_MODE_WOR + #define RPL_PKT_RECV_BUF_SIZE 20 #define RPL_PROCESS_STACKSIZE 4096 diff --git a/sys/net/sixlowpan/rpl/rpl_dodag.c b/sys/net/sixlowpan/rpl/rpl_dodag.c index 71014f843c..d446108a7b 100644 --- a/sys/net/sixlowpan/rpl/rpl_dodag.c +++ b/sys/net/sixlowpan/rpl/rpl_dodag.c @@ -7,7 +7,6 @@ rpl_instance_t instances[RPL_MAX_INSTANCES]; rpl_dodag_t dodags[RPL_MAX_DODAGS]; -rpl_candidate_neighbor_t candidates[RPL_MAX_CANDIDATE_NEIGHBORS]; rpl_parent_t parents[RPL_MAX_PARENTS]; rpl_instance_t *rpl_new_instance(uint8_t instanceid){ @@ -74,7 +73,7 @@ rpl_dodag_t *rpl_get_dodag(ipv6_addr_t *id){ } return NULL; } -rpl_dodag_t *rpl_get_my_dodag(){ +rpl_dodag_t *rpl_get_my_dodag(void){ for(int i=0;igrounded = dodag->grounded; my_dodag->joined = 1; my_dodag->my_preferred_parent = preferred_parent; - my_dodag->my_rank = dodag->of->calc_rank(); + my_dodag->node_status = (uint8_t) NORMAL_NODE; + 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; - - //OF specific initialisation, the rootnode does this at the beginning - //when constructing a dodag - if(my_dodag->of->init != NULL){ - my_dodag->of->init(); - } - start_trickle(my_dodag->dio_min, my_dodag->dio_interval_doubling, my_dodag->dio_redundancy); delay_dao(); } @@ -286,7 +279,7 @@ void rpl_global_repair(rpl_dodag_t *dodag, ipv6_addr_t * p_addr, uint16_t rank){ my_dodag->my_rank = INFINITE_RANK; }else{ //Calc new Rank - my_dodag->my_rank = my_dodag->of->calc_rank(); + my_dodag->my_rank = my_dodag->of->calc_rank(my_dodag->my_preferred_parent, my_dodag->my_rank); my_dodag->min_rank = my_dodag->my_rank; reset_trickletimer(); delay_dao(); diff --git a/sys/net/sixlowpan/rpl/rpl_dodag.h b/sys/net/sixlowpan/rpl/rpl_dodag.h index 174628c911..44f0118e10 100644 --- a/sys/net/sixlowpan/rpl/rpl_dodag.h +++ b/sys/net/sixlowpan/rpl/rpl_dodag.h @@ -1,12 +1,11 @@ #include "rpl_structs.h" -//#include "of0.h" rpl_instance_t *rpl_new_instance(uint8_t instanceid); rpl_instance_t *rpl_get_instance(uint8_t instanceid); rpl_instance_t *rpl_get_my_instance(); rpl_dodag_t *rpl_new_dodag(uint8_t instanceid, ipv6_addr_t *id); rpl_dodag_t *rpl_get_dodag(ipv6_addr_t *id); -rpl_dodag_t *rpl_get_my_dodag(); +rpl_dodag_t *rpl_get_my_dodag(void); void rpl_join_dodag(rpl_dodag_t *dodag, ipv6_addr_t *parent, uint16_t parent_rank); void rpl_del_dodag(rpl_dodag_t *dodag); rpl_parent_t *rpl_new_parent(rpl_dodag_t *dodag, ipv6_addr_t *address, uint16_t rank); diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index 45eb4d43d5..c2a4060fba 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -52,6 +52,14 @@ #define RPL_COUNTER_GREATER_THAN_LOCAL(A,B) (((A B) && (A-B < RPL_COUNTER_SEQ_WINDOW))) #define RPL_COUNTER_GREATER_THAN(A,B) ((A>RPL_COUNTER_LOWER_REGION) ? ((B > RPL_COUNTER_LOWER_REGION ) ? RPL_COUNTER_GREATER_THAN_LOCAL(A,B) : 0): (( B>RPL_COUNTER_LOWER_REGION ) ? 1: RPL_COUNTER_GREATER_THAN_LOCAL(A,B))) +// Node Status +#define NORMAL_NODE 0 +#define ROOT_NODE 1 +#define LEAF_NODE 2 + +// Link Metric Type +#define METRIC_ETX 1 + // Default values #define RPL_DEFAULT_MOP STORING_MODE_NO_MC @@ -97,7 +105,7 @@ #define RPL_DIS_I_MASK 0x40 #define RPL_DIS_D_MASK 0x20 #define RPL_GROUNDED_SHIFT 7 -#define RPL_DEFAULT_OCP 0 +#define RPL_DEFAULT_OCP 1 //DIO Base Object (RFC 6550 Fig. 14) struct __attribute__((packed)) rpl_dio_t{ @@ -193,20 +201,25 @@ typedef struct __attribute__((packed)) rpl_opt_transit_t { struct rpl_dodag_t; typedef struct rpl_candidate_neighbor_t { - ipv6_addr_t addr; - struct rpl_dodag_t *dodag; - uint8_t used; + ipv6_addr_t addr; //The address of this node + uint8_t packets_rx; //The packets this node has received FROM ME + double cur_etx; //The currently calculated ETX-value + uint8_t used; //The indicator if this node is active or not } rpl_candidate_neighbor_t; typedef struct rpl_parent_t { - ipv6_addr_t addr; - uint16_t rank; - uint8_t dtsn; + ipv6_addr_t addr; + uint16_t rank; + uint8_t dtsn; struct rpl_dodag_t *dodag; - uint16_t lifetime; - uint8_t used; + uint16_t lifetime; + double link_metric; + uint8_t link_metric_type; + uint8_t used; } rpl_parent_t; +struct rpl_of_t; + typedef struct rpl_instance_t { //struct rpl_dodag_t *current_dodoag; uint8_t id; @@ -215,6 +228,7 @@ typedef struct rpl_instance_t { } rpl_instance_t; +//Node-internal representation of a DODAG, with nodespecific information typedef struct rpl_dodag_t { rpl_instance_t *instance; ipv6_addr_t dodag_id; @@ -232,6 +246,7 @@ typedef struct rpl_dodag_t { uint8_t version; uint8_t grounded; uint16_t my_rank; + uint8_t node_status; uint8_t dao_seq; uint16_t min_rank; uint8_t joined; @@ -241,7 +256,7 @@ typedef struct rpl_dodag_t { typedef struct rpl_of_t { uint16_t ocp; - uint16_t (*calc_rank)(); + uint16_t (*calc_rank)(rpl_parent_t * parent, uint16_t base_rank); rpl_parent_t *(*which_parent)(rpl_parent_t *, rpl_parent_t *); rpl_dodag_t *(*which_dodag)(rpl_dodag_t *, rpl_dodag_t *); void (*reset)(struct rpl_dodag_t *); diff --git a/sys/vtimer.c b/sys/vtimer.c index 9ca66adc66..53784b8d57 100644 --- a/sys/vtimer.c +++ b/sys/vtimer.c @@ -117,9 +117,13 @@ void vtimer_callback(void *ptr) { msg.type = MSG_TIMER; msg.content.value = (unsigned int) timer->arg; msg_send_int(&msg, timer->pid); - } else { + } + else if (timer->action == (void*) thread_wakeup){ timer->action(timer->arg); - } + }else { + puts("Timer was poisoned");//TODO delete this debug message + DEBUG("Timer was poisoned."); + } in_callback = false; update_shortterm(); @@ -251,6 +255,14 @@ int vtimer_set_msg(vtimer_t *t, timex_t interval, unsigned int pid, void *ptr){ return 0; } +void vtimer_print_short_queue(){ + queue_print(&shortterm_queue_root); +} + +void vtimer_print_long_queue(){ + queue_print(&longterm_queue_root); +} + #ifdef ENABLE_DEBUG static void vtimer_print(vtimer_t* t) { printf("Seconds: %lu - Microseconds: %lu\n \ From 5a2bc468c493569dadd382ba2a8e7eef5df63bf9 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Mon, 18 Mar 2013 19:22:07 +0100 Subject: [PATCH 24/35] threads dont overflow anymore, still hangs at random counts of sent beacon packets --- board/msba2-common/tools/src/control_2xxx.c | 6 +- projects/test_beacon/main.c | 1 + sys/net/sixlowpan/rpl/etx_beaconing.c | 79 +++++---------------- 3 files changed, 21 insertions(+), 65 deletions(-) diff --git a/board/msba2-common/tools/src/control_2xxx.c b/board/msba2-common/tools/src/control_2xxx.c index ac0c8ca975..6843fec204 100644 --- a/board/msba2-common/tools/src/control_2xxx.c +++ b/board/msba2-common/tools/src/control_2xxx.c @@ -13,7 +13,7 @@ void hard_reset_to_bootloader(void) getchar(); */ printf("Reset CPU (into bootloader)\r\n"); - set_rts(0); // RTS (ttl level) connects to P0.14 + set_rts(1); // RTS (ttl level) connects to P0.14 /* the next two lines should be commented for the prepared node */ set_dtr(1); // DTR (ttl level) connects to RST send_break_signal(); // or break detect circuit to RST @@ -24,14 +24,14 @@ void hard_reset_to_bootloader(void) */ set_dtr(0); // allow the CPU to run: set_baud(baud_rate); - set_rts(0); // set RTS again (as it has been reset by set_baudrate) + set_rts(1); // set RTS again (as it has been reset by set_baudrate) usleep(40000); } void hard_reset_to_user_code(void) { printf("Reset CPU (into user code)\r\n"); - set_rts(1); // RTS (ttl level) connects to P0.14 + set_rts(0); // RTS (ttl level) connects to P0.14 set_dtr(1); // DTR (ttl level) connects to RST send_break_signal(); // or break detect circuit to RST usleep(75000); diff --git a/projects/test_beacon/main.c b/projects/test_beacon/main.c index 66c48be18c..f92d56f513 100644 --- a/projects/test_beacon/main.c +++ b/projects/test_beacon/main.c @@ -59,6 +59,7 @@ void init(char *str){ void table(char *str){ thread_print_all(); + show_candidates(); } const shell_command_t shell_commands[] = { diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index 1386075059..5e3f38d760 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -75,6 +75,8 @@ static etx_probe_t * get_etx_rec_buf(void) { //TODO delete void etx_beacon2(void); +void etx_radio2(void); + void show_candidates(void) { //TODO delete /* @@ -104,79 +106,34 @@ void show_candidates(void) { void etx_init_beaconing(ipv6_addr_t * address) { own_address = address; - show_candidates(); -//set code + //set code printf("ETX BEACON INIT"); etx_send_buf[0] = ETX_BEACON; thread_print_all(); - // etx_beacon_pid = thread_create(etx_beacon_buf, ETX_BEACON_STACKSIZE, - // PRIORITY_MAIN - 1, CREATE_STACKTEST, - // etx_beacon2, "etx_beacon"); + etx_beacon_pid = thread_create(etx_beacon_buf, ETX_BEACON_STACKSIZE, + PRIORITY_MAIN - 1, CREATE_STACKTEST, + etx_beacon, "etx_beacon"); etx_radio_pid = thread_create(etx_radio_buf, ETX_RADIO_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, etx_radio, "etx_radio"); - printf("etx radio pid is %d", etx_radio_pid); /* * Maybe this should not be in a seperate thread resource-wise, but the * motive was to delay beacon-sending as little as possible, as this would * derail beaconing from the intended ETX_INTERVAL. */ - //TODO delete - show_candidates(); - etx_update_pid = thread_create(etx_update_buf, ETX_UPDT_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, etx_update, "etx_update"); - //TODO delete - show_candidates(); - - //TODO delete - thread_wakeup(etx_update_pid); - //register at transceiver transceiver_register(TRANSCEIVER_CC1100, etx_radio_pid); printf("...[DONE]\n"); } -void etx_beacon2(void) { -//TODO delete or delete beacon, whatever do use 1 method and del the other - etx_probe_t *etx_p = get_etx_send_buf(); - - ieee_802154_long_t empty_addr = { 0 }; - - uint8_t jittercorrection = 10; - uint8_t jitter = (uint8_t) (rand() % 21); - uint8_t p_length = 0; - - while (true) { - if (rounds == ETX_ROUNDS) { - //calculate the ETX values and update the parents - thread_wakeup(etx_update_pid); - rounds = 1; - } else { - rounds++; - } - - vtimer_usleep(80 * MS + jittercorrection * MS + jitter * MS); - /// TODO once vtimer works as intended, replace the hwtimer here with - /// the vtimer. Right now vtimer bugs, so we have hwtimer here. - //hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); - - jittercorrection = 20 - jitter; - - //the jitter is a value between 0 and 20 - jitter = (uint8_t) (rand() % 21); - printf("jitter: %d", jitter); - puts("beacon2 run through complete"); - show_candidates(); - } -} - void etx_beacon(void) { /* * TODO use ETX_INTERVAL variable instead of fixed value @@ -217,17 +174,16 @@ void etx_beacon(void) { send_ieee802154_frame(&empty_addr, &etx_send_buf[0], get_etx_send_buf()->length + 2, 1); puts("sent beacon!"); - //hwtimer buggt noch mehr als der vtimer... - vtimer_usleep(80 * MS + jittercorrection * MS + jitter * MS); + //vtimer_usleep(80 * MS + jittercorrection * MS + jitter * MS); /// TODO once vtimer works as intended, replace the hwtimer here with /// the vtimer. Right now vtimer bugs, so we have hwtimer here. - //hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); + /// hangs after 38 runthroughs (roughly 1 minute, a bit more) + hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); jittercorrection = 20 - jitter; //the jitter is a value between 0 and 20 jitter = (uint8_t) (rand() % 21); - printf("jitter: %d", jitter); } } @@ -261,7 +217,7 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { etx_probe_t * probe = get_etx_rec_buf(); -//Todo delete once everything works well + //Todo delete once everything works well printf("ETX beacon package received with following values:\n" "\tPackage Option:%x\n" "\t Data Length:%u\n" @@ -297,11 +253,11 @@ void etx_radio(void) { msg_init_queue(msg_que, ETX_RCV_BUFFER_SIZE); -// ipv6_addr_t ll_address; -// ipv6_addr_t candidate_addr; + ipv6_addr_t ll_address; + ipv6_addr_t candidate_addr; -// ipv6_set_ll_prefix(&ll_address); -// ipv6_get_saddr(&candidate_addr, &ll_address); + ipv6_set_ll_prefix(&ll_address); + ipv6_get_saddr(&candidate_addr, &ll_address); while (1) { puts("radio"); //TODO del @@ -319,10 +275,9 @@ void etx_radio(void) { //create IPv6 address from radio packet //we can do the cast here since rpl nodes can only have addr //up to 8 bits - // candidate_addr.uint8[15] = (uint8_t) p->src; + candidate_addr.uint8[15] = (uint8_t) p->src; //handle the beacon - // etx_handle_beacon(&candidate_addr); - etx_handle_beacon(0); + etx_handle_beacon(&candidate_addr); } p->processing--; @@ -347,7 +302,7 @@ void etx_update(void) { * */ rpl_candidate_neighbor_t * candidate; - rpl_candidate_neighbor_t *end; + rpl_candidate_neighbor_t * end; while (true) { //good night From 07a7f107982cd8d5d113069d99afc5baf952311f Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 19 Mar 2013 14:04:23 +0100 Subject: [PATCH 25/35] changed buffer sizes for debugging --- sys/net/sixlowpan/rpl/etx_beaconing.c | 39 +++++++++++++-------------- sys/net/sixlowpan/rpl/etx_beaconing.h | 20 ++++++++++---- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index 5e3f38d760..3ecefef921 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -73,9 +73,6 @@ static etx_probe_t * get_etx_rec_buf(void) { return ((etx_probe_t *) &(etx_rec_buf[0])); } -//TODO delete -void etx_beacon2(void); -void etx_radio2(void); void show_candidates(void) { //TODO delete @@ -84,7 +81,7 @@ void show_candidates(void) { printf("Candidates Addr:%d\n" "\t cur_etx:%f\n" "\t packets_rx:%d\n" - "\t used:%d\n", candidates[i].addr.uint8[15], + "\t used:%d\n", candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE], candidates[i].cur_etx, candidates[i].packets_rx, candidates[i].used); } @@ -98,7 +95,7 @@ void show_candidates(void) { printf("Candidates Addr:%d\n" "\t cur_etx:%f\n" "\t packets_rx:%d\n" - "\t used:%d\n", candidate->addr.uint8[15], + "\t used:%d\n", candidate->addr.uint8[ETX_IPV6_LAST_BYTE], candidate->cur_etx, candidate->packets_rx, candidate->used); } @@ -143,8 +140,8 @@ void etx_beacon(void) { * and modifies the time to wait accordingly. */ etx_probe_t *etx_p = get_etx_send_buf(); - uint8_t jittercorrection = 10; - uint8_t jitter = (uint8_t) (rand() % 21); + uint8_t jittercorrection = ETX_DEF_JIT_CORRECT; + uint8_t jitter = (uint8_t) (rand() % ETX_JITTER_MOD); uint8_t p_length = 0; @@ -164,15 +161,15 @@ void etx_beacon(void) { p_length = 0; for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { if (candidates[i].used != 0) { - etx_p->data[i * 2] = candidates[i].addr.uint8[15]; - etx_p->data[i * 2 + 1] = candidates[i].packets_rx; - p_length = p_length + 2; + etx_p->data[i * ETX_TUPLE_SIZE] = candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; + etx_p->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = candidates[i].packets_rx; + p_length = p_length + ETX_PKT_HDR_LEN; } } etx_p->length = p_length; send_ieee802154_frame(&empty_addr, &etx_send_buf[0], - get_etx_send_buf()->length + 2, 1); + get_etx_send_buf()->length + ETX_PKT_HDR_LEN, 1); puts("sent beacon!"); //vtimer_usleep(80 * MS + jittercorrection * MS + jitter * MS); /// TODO once vtimer works as intended, replace the hwtimer here with @@ -183,7 +180,7 @@ void etx_beacon(void) { jittercorrection = 20 - jitter; //the jitter is a value between 0 and 20 - jitter = (uint8_t) (rand() % 21); + jitter = (uint8_t) (rand() % ETX_JITTER_MOD); } } @@ -222,23 +219,23 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { "\tPackage Option:%x\n" "\t Data Length:%u\n" "\tSource Address:%d\n\n", probe->code, probe->length, - candidate_address->uint8[15]); + candidate_address->uint8[ETX_IPV6_LAST_BYTE]); rpl_candidate_neighbor_t* candidate = NULL; - for (uint8_t i = 0; i < probe->length / 2; i++) { + for (uint8_t i = 0; i < probe->length / ETX_TUPLE_SIZE; i++) { //todo delete once everything works well printf("\tIPv6 short Addr:%u\n" - "\tPackets f. Addr:%u\n\n", probe->data[i * 2], - probe->data[i * 2 + 1]); + "\tPackets f. Addr:%u\n\n", probe->data[i * ETX_TUPLE_SIZE], + probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); // If i find my address in this probe, update the packet_rx value for // this candidate, if he is in my candidate list. - if (probe->data[i * 2] == own_address->uint8[15]) { + if (probe->data[i * ETX_TUPLE_SIZE] == own_address->uint8[ETX_IPV6_LAST_BYTE]) { //candidate = etx_find_candidate(candidate_address); - candidate = NULL; + candidate = NULL;//TODO delete if (candidate != NULL ) { - candidate->packets_rx = probe->data[i * 2 + 1]; + candidate->packets_rx = probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]; } } } @@ -275,7 +272,7 @@ void etx_radio(void) { //create IPv6 address from radio packet //we can do the cast here since rpl nodes can only have addr //up to 8 bits - candidate_addr.uint8[15] = (uint8_t) p->src; + candidate_addr.uint8[ETX_IPV6_LAST_BYTE] = (uint8_t) p->src; //handle the beacon etx_handle_beacon(&candidate_addr); } @@ -316,7 +313,7 @@ void etx_update(void) { if (candidate->used != 0) { //update its ETX-metric and packet count TODO mutex this - candidate->cur_etx = candidate->packets_rx / (double) 10; + candidate->cur_etx = candidate->packets_rx / (double) ETX_ROUNDS; candidate->packets_rx = 0; printf( "Updated ETX Metric to %f for candidate used was on %d", diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index 96b0f9815d..8ce8ffd299 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -11,20 +11,30 @@ #include "sys/net/sixlowpan/sixlowip.h" -#define ETX_BEACON_STACKSIZE 1024 -#define ETX_RADIO_STACKSIZE 1024 -#define ETX_UPDT_STACKSIZE 256 +#define ETX_BEACON_STACKSIZE 4500 //TODO debug stacksize, set for production +#define ETX_RADIO_STACKSIZE 4500 //TODO debug stacksize, set for production +#define ETX_UPDT_STACKSIZE 4500 //TODO debug stacksize, set for production #define ETX_INTERVAL 1000000 //1 Second in us is the default value #define ETX_ROUNDS 10 //10 is the default value + //[option|length|ipaddr.|packetcount] with up to 15 ipaddr|packetcount pairs // 1 Byte 1 Byte 1 Byte 1 Byte #define ETX_BUF_SIZE (32) #define ETX_RCV_BUFFER_SIZE (128) -//ETX beaconing type (!ATTENTION! this is non-standard) -#define ETX_BEACON 0x20 +//Constants for packets + +//ETX beaconing type (XXX ATTENTION! this is non-standard) +#define ETX_BEACON 0x20//Non-standard way of saying this is an etx-pkt. + +#define ETX_PKT_HDR_LEN 2 //Option type + Length (1 Byte each) +#define ETX_TUPLE_SIZE 2 //1 Byte for Addr, 1 Byte for packets rec. +#define ETX_PKT_REC_OFFSET 1 //Offset in a tuple of (addr,pkt_rec) +#define ETX_IPV6_LAST_BYTE 15 //The last byte for an ipv6 address +#define ETX_JITTER_MOD 21 //The modulo value for jitter computation +#define ETX_DEF_JIT_CORRECT (ETX_JITTER_MOD - 1) / 2 //Default Jitter correction value (normally ETX_JITTER_MOD -1 / 2) //prototypes void etx_init_beaconing(ipv6_addr_t * address); From c161b43d7870a9d28647c214364891fbebe0d5c9 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Tue, 19 Mar 2013 14:07:31 +0100 Subject: [PATCH 26/35] changed some printf statements into puts --- sys/net/sixlowpan/rpl/etx_beaconing.c | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index 3ecefef921..c2b24f6b43 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -75,17 +75,6 @@ static etx_probe_t * get_etx_rec_buf(void) { void show_candidates(void) { - //TODO delete - /* - for (int i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { - printf("Candidates Addr:%d\n" - "\t cur_etx:%f\n" - "\t packets_rx:%d\n" - "\t used:%d\n", candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE], - candidates[i].cur_etx, candidates[i].packets_rx, - candidates[i].used); - } - */ rpl_candidate_neighbor_t * candidate; rpl_candidate_neighbor_t *end; @@ -104,7 +93,7 @@ void show_candidates(void) { void etx_init_beaconing(ipv6_addr_t * address) { own_address = address; //set code - printf("ETX BEACON INIT"); + puts("ETX BEACON INIT"); etx_send_buf[0] = ETX_BEACON; thread_print_all(); @@ -126,9 +115,9 @@ void etx_init_beaconing(ipv6_addr_t * address) { PRIORITY_MAIN - 1, CREATE_STACKTEST, etx_update, "etx_update"); -//register at transceiver + //register at transceiver transceiver_register(TRANSCEIVER_CC1100, etx_radio_pid); - printf("...[DONE]\n"); + puts("...[DONE]"); } void etx_beacon(void) { @@ -174,7 +163,6 @@ void etx_beacon(void) { //vtimer_usleep(80 * MS + jittercorrection * MS + jitter * MS); /// TODO once vtimer works as intended, replace the hwtimer here with /// the vtimer. Right now vtimer bugs, so we have hwtimer here. - /// hangs after 38 runthroughs (roughly 1 minute, a bit more) hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); jittercorrection = 20 - jitter; @@ -207,7 +195,6 @@ double etx_get_metric(ipv6_addr_t * address) { } void etx_handle_beacon(ipv6_addr_t * candidate_address) { - puts("handle_beacon"); //TODO del /* * Handle the ETX probe that has been received and update all infos. */ @@ -257,9 +244,7 @@ void etx_radio(void) { ipv6_get_saddr(&candidate_addr, &ll_address); while (1) { - puts("radio"); //TODO del msg_receive(&m); - puts("msg received"); if (m.type == PKT_PENDING) { p = (radio_packet_t*) m.content.ptr; From dccc377f83faf5277ab71eda170f3bc7cf05b85f Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Fri, 22 Mar 2013 17:40:36 +0100 Subject: [PATCH 27/35] Changed value for maximum candidate neighbors to 40 Replaced lots of different constants written as numbers by proberply defined constant-variables Changed usage of fixed values for the hwtimer_wait in send_beacon to customizable constants --- sys/net/sixlowpan/rpl/etx_beaconing.c | 108 ++++++++++++++++++++------ sys/net/sixlowpan/rpl/etx_beaconing.h | 20 +++-- sys/net/sixlowpan/rpl/rpl_structs.h | 6 +- 3 files changed, 103 insertions(+), 31 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index c2b24f6b43..cdb137e359 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -20,8 +20,6 @@ #include "rpl_structs.h" #include "rpl_dodag.h" -#define MS 10000 - int etx_beacon_pid = 0; int etx_radio_pid = 0; int etx_update_pid = 0; @@ -73,7 +71,6 @@ static etx_probe_t * get_etx_rec_buf(void) { return ((etx_probe_t *) &(etx_rec_buf[0])); } - void show_candidates(void) { rpl_candidate_neighbor_t * candidate; rpl_candidate_neighbor_t *end; @@ -122,13 +119,19 @@ void etx_init_beaconing(ipv6_addr_t * address) { void etx_beacon(void) { /* - * TODO use ETX_INTERVAL variable instead of fixed value - * Sends a message every ETX_INTERVAL +/- a small jitter-value. + * Sends a message every ETX_INTERVAL +/- a jitter-value (default is 10%) . * A correcting variable is needed to stay at a base interval of * ETX_INTERVAL between the wakeups. It takes the old jittervalue in account * and modifies the time to wait accordingly. */ etx_probe_t *etx_p = get_etx_send_buf(); + + /* + * The jittercorrection and jitter variables keep usecond values divided + * through 1000 to fit into uint8 variables. + * + * That is why they are multiplied by 1000 when used for hwtimer_wait. + */ uint8_t jittercorrection = ETX_DEF_JIT_CORRECT; uint8_t jitter = (uint8_t) (rand() % ETX_JITTER_MOD); @@ -150,8 +153,10 @@ void etx_beacon(void) { p_length = 0; for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { if (candidates[i].used != 0) { - etx_p->data[i * ETX_TUPLE_SIZE] = candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; - etx_p->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = candidates[i].packets_rx; + etx_p->data[i * ETX_TUPLE_SIZE] = + candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; + etx_p->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = + candidates[i].packets_rx; p_length = p_length + ETX_PKT_HDR_LEN; } } @@ -160,14 +165,14 @@ void etx_beacon(void) { send_ieee802154_frame(&empty_addr, &etx_send_buf[0], get_etx_send_buf()->length + ETX_PKT_HDR_LEN, 1); puts("sent beacon!"); - //vtimer_usleep(80 * MS + jittercorrection * MS + jitter * MS); + //vtimer_usleep(ETX_INTERVAL - ETX_MAX_JITTER + jittercorrection*MS + jitter*MS); /// TODO once vtimer works as intended, replace the hwtimer here with /// the vtimer. Right now vtimer bugs, so we have hwtimer here. - hwtimer_wait(HWTIMER_TICKS(80*MS + jittercorrection*MS + jitter*MS)); + hwtimer_wait(HWTIMER_TICKS(ETX_INTERVAL - ETX_MAX_JITTER + jittercorrection*MS + jitter*MS)); - jittercorrection = 20 - jitter; + jittercorrection = (ETX_MAX_JITTER/MS) - jitter; - //the jitter is a value between 0 and 20 + //the jitter is a value between 0 and ETX_MAX_JITTER jitter = (uint8_t) (rand() % ETX_JITTER_MOD); } } @@ -177,12 +182,12 @@ rpl_candidate_neighbor_t * etx_find_candidate(ipv6_addr_t * address) { * find the candidate with address address and returns it, or returns NULL * if no candidate having this address was found. */ - //for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { - // if (candidates[i].used - // && (rpl_equal_id(&candidates[i].addr, address))) { - // return &candidates[i]; - // } - //} + for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + if (candidates[i].used + && (rpl_equal_id(&candidates[i].addr, address))) { + return &candidates[i]; + } + } return NULL ; } @@ -194,9 +199,55 @@ double etx_get_metric(ipv6_addr_t * address) { return 0; } +uint8_t etx_add_candidate(ipv6_addr_t * address, uint8_t * pkt_rcvd) { + /* + * Pre-Condition: Add etx_add_candidate should only be called when the + * candidate is not yet in the list. + * Otherwise the candidate will be added a second time, + * leading to unknown behavior. + * + * Check if there is still enough space to add this candidate + * + * a) + * Space is available: + * Add candidate + * + * b) + * Space is not available: + * ignore new candidate + * This shouldn't really happen though, since we have enough + * place in the array. + * + * Returns if the candidate was added (1) or not (0). + */ + rpl_candidate_neighbor_t * candidate; + rpl_candidate_neighbor_t * end; + uint8_t added = 0; + + for (candidate = &candidates[0], end = candidates + + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; + candidate++) { + if (candidate->used) { + //skip + continue; + } else { + //We still have a free place add the new candidate + candidate->addr = address; + candidate->cur_etx = 0; + candidate->packets_rx = *pkt_rcvd; + candidate->used = 1; + + added = 1; + break; + } + } + return added; +} + void etx_handle_beacon(ipv6_addr_t * candidate_address) { /* * Handle the ETX probe that has been received and update all infos. + * If the candidate address is unknown, try to add it to my struct. */ etx_probe_t * probe = get_etx_rec_buf(); @@ -218,11 +269,21 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { // If i find my address in this probe, update the packet_rx value for // this candidate, if he is in my candidate list. - if (probe->data[i * ETX_TUPLE_SIZE] == own_address->uint8[ETX_IPV6_LAST_BYTE]) { - //candidate = etx_find_candidate(candidate_address); - candidate = NULL;//TODO delete + if (probe->data[i * ETX_TUPLE_SIZE] + == own_address->uint8[ETX_IPV6_LAST_BYTE]) { + candidate = etx_find_candidate(candidate_address); if (candidate != NULL ) { - candidate->packets_rx = probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]; + candidate->packets_rx = probe->data[i * ETX_TUPLE_SIZE + + ETX_PKT_REC_OFFSET]; + } else { + //Candidate was not found in my list, maybe I should add it + uint8_t addresult = 0; + addresult = etx_add_candidate(candidate_address, + probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); + + if(addresult == 1){ + puts("[WARNING] Candidate could not get added"); + } } } } @@ -298,7 +359,10 @@ void etx_update(void) { if (candidate->used != 0) { //update its ETX-metric and packet count TODO mutex this - candidate->cur_etx = candidate->packets_rx / (double) ETX_ROUNDS; + //TODO probably better to change floating point-math to integer + //based math + candidate->cur_etx = + candidate->packets_rx / (double) ETX_ROUNDS; candidate->packets_rx = 0; printf( "Updated ETX Metric to %f for candidate used was on %d", diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index 8ce8ffd299..c8b9012dad 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -14,8 +14,6 @@ #define ETX_BEACON_STACKSIZE 4500 //TODO debug stacksize, set for production #define ETX_RADIO_STACKSIZE 4500 //TODO debug stacksize, set for production #define ETX_UPDT_STACKSIZE 4500 //TODO debug stacksize, set for production -#define ETX_INTERVAL 1000000 //1 Second in us is the default value -#define ETX_ROUNDS 10 //10 is the default value //[option|length|ipaddr.|packetcount] with up to 15 ipaddr|packetcount pairs @@ -29,12 +27,18 @@ //ETX beaconing type (XXX ATTENTION! this is non-standard) #define ETX_BEACON 0x20//Non-standard way of saying this is an etx-pkt. -#define ETX_PKT_HDR_LEN 2 //Option type + Length (1 Byte each) -#define ETX_TUPLE_SIZE 2 //1 Byte for Addr, 1 Byte for packets rec. -#define ETX_PKT_REC_OFFSET 1 //Offset in a tuple of (addr,pkt_rec) -#define ETX_IPV6_LAST_BYTE 15 //The last byte for an ipv6 address -#define ETX_JITTER_MOD 21 //The modulo value for jitter computation -#define ETX_DEF_JIT_CORRECT (ETX_JITTER_MOD - 1) / 2 //Default Jitter correction value (normally ETX_JITTER_MOD -1 / 2) +//ETX Interval parameters +#define MS 1000 + +#define ETX_INTERVAL (1000 * MS) //Given in us, the default is 1 second +#define ETX_ROUNDS (10) //10 is the default value +#define ETX_PKT_HDR_LEN (2) //Option type + Length (1 Byte each) +#define ETX_TUPLE_SIZE (2) //1 Byte for Addr, 1 Byte for packets rec. +#define ETX_PKT_REC_OFFSET (1) //Offset in a tuple of (addr,pkt_rec) +#define ETX_IPV6_LAST_BYTE (15) //The last byte for an ipv6 address +#define ETX_MAX_JITTER (ETX_INTERVAL/5) //The default value is 20% of ETX_INTERVAL +#define ETX_JITTER_MOD (ETX_MAX_JITTER/MS + 1) //The modulo value for jitter computation +#define ETX_DEF_JIT_CORRECT (ETX_MAX_JITTER/MS / 2) //Default Jitter correction value (normally ETX_MAX_JITTER / 2) //prototypes void etx_init_beaconing(ipv6_addr_t * address); diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index c2a4060fba..8000bf7631 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -91,7 +91,11 @@ #define NUMBER_IMPLEMENTED_OFS 2 #define RPL_MAX_DODAGS 3 #define RPL_MAX_INSTANCES 1 -#define RPL_MAX_CANDIDATE_NEIGHBORS 15 +/* + * Default 40, should be enough to get all messages for neighbors. + * In my tests, the maximum count of neighbors was around 30-something + */ +#define RPL_MAX_CANDIDATE_NEIGHBORS 40 #define RPL_MAX_PARENTS 5 #define RPL_MAX_ROUTING_ENTRIES 128 #define RPL_ROOT_RANK 1 From 85211f84083f58d3861527d4f6ea3d6a90170a12 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Fri, 22 Mar 2013 18:37:00 +0100 Subject: [PATCH 28/35] changed some of the ETX constants to be more easily understandable --- sys/net/sixlowpan/rpl/etx_beaconing.c | 6 +++--- sys/net/sixlowpan/rpl/etx_beaconing.h | 17 ++++++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index cdb137e359..df97995fc5 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -165,12 +165,12 @@ void etx_beacon(void) { send_ieee802154_frame(&empty_addr, &etx_send_buf[0], get_etx_send_buf()->length + ETX_PKT_HDR_LEN, 1); puts("sent beacon!"); - //vtimer_usleep(ETX_INTERVAL - ETX_MAX_JITTER + jittercorrection*MS + jitter*MS); + //vtimer_usleep(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS); /// TODO once vtimer works as intended, replace the hwtimer here with /// the vtimer. Right now vtimer bugs, so we have hwtimer here. - hwtimer_wait(HWTIMER_TICKS(ETX_INTERVAL - ETX_MAX_JITTER + jittercorrection*MS + jitter*MS)); + hwtimer_wait(HWTIMER_TICKS(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS)); - jittercorrection = (ETX_MAX_JITTER/MS) - jitter; + jittercorrection = (ETX_MAX_JITTER) - jitter; //the jitter is a value between 0 and ETX_MAX_JITTER jitter = (uint8_t) (rand() % ETX_JITTER_MOD); diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index c8b9012dad..b2f1312fa8 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -30,15 +30,22 @@ //ETX Interval parameters #define MS 1000 -#define ETX_INTERVAL (1000 * MS) //Given in us, the default is 1 second +/* + * ETX_INTERVAL + * + * Given in ms, the default is 1 second. + * Should be divisible through 2 (For ETX_DEF_JIT_CORRECT) + * and 5 (For ETX_MAX_JITTER) unless those values are adjusted too. + */ +#define ETX_INTERVAL (1000) #define ETX_ROUNDS (10) //10 is the default value #define ETX_PKT_HDR_LEN (2) //Option type + Length (1 Byte each) #define ETX_TUPLE_SIZE (2) //1 Byte for Addr, 1 Byte for packets rec. -#define ETX_PKT_REC_OFFSET (1) //Offset in a tuple of (addr,pkt_rec) +#define ETX_PKT_REC_OFFSET (ETX_TUPLE_SIZE - 1) //Offset in a tuple of (addr,pkt_rec), will always be the last byte #define ETX_IPV6_LAST_BYTE (15) //The last byte for an ipv6 address -#define ETX_MAX_JITTER (ETX_INTERVAL/5) //The default value is 20% of ETX_INTERVAL -#define ETX_JITTER_MOD (ETX_MAX_JITTER/MS + 1) //The modulo value for jitter computation -#define ETX_DEF_JIT_CORRECT (ETX_MAX_JITTER/MS / 2) //Default Jitter correction value (normally ETX_MAX_JITTER / 2) +#define ETX_MAX_JITTER (ETX_INTERVAL / 5) //The default value is 20% of ETX_INTERVAL +#define ETX_JITTER_MOD (ETX_MAX_JITTER + 1) //The modulo value for jitter computation +#define ETX_DEF_JIT_CORRECT (ETX_MAX_JITTER / 2) //Default Jitter correction value (normally ETX_MAX_JITTER / 2) //prototypes void etx_init_beaconing(ipv6_addr_t * address); From a7c0e325a78f9ecba13bd380ad26833795d99e46 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Sun, 24 Mar 2013 15:53:57 +0100 Subject: [PATCH 29/35] added a seperate shellcommand to show candidates --- projects/test_beacon/main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/projects/test_beacon/main.c b/projects/test_beacon/main.c index f92d56f513..eafd39d9d3 100644 --- a/projects/test_beacon/main.c +++ b/projects/test_beacon/main.c @@ -59,12 +59,16 @@ void init(char *str){ void table(char *str){ thread_print_all(); +} + +void candidates(char *str){ show_candidates(); } const shell_command_t shell_commands[] = { {"init", "", init}, {"table", "", table}, + {"cand", "", candidates}, {NULL, NULL, NULL} }; From 2ae2d85b107d452abf007c7f7a7920f60e41e297 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Sun, 24 Mar 2013 15:57:52 +0100 Subject: [PATCH 30/35] changed some buffer sizes and other minimal stuff --- sys/net/sixlowpan/rpl/etx_beaconing.c | 8 ++++---- sys/net/sixlowpan/rpl/etx_beaconing.h | 8 ++++---- sys/net/sixlowpan/rpl/rpl_structs.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index df97995fc5..c05bdc5f64 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -40,7 +40,7 @@ uint8_t etx_rec_buf[ETX_BUF_SIZE] = { 0 }; static uint8_t rounds = 0; //Message queue for radio -msg_t msg_que[ETX_RCV_BUFFER_SIZE] = { 0 }; +msg_t msg_que[ETX_RCV_QUEUE_SIZE] = { 0 }; /* * This could (and should) be done differently, once the RPL implementation @@ -232,7 +232,7 @@ uint8_t etx_add_candidate(ipv6_addr_t * address, uint8_t * pkt_rcvd) { continue; } else { //We still have a free place add the new candidate - candidate->addr = address; + candidate->addr = * address; candidate->cur_etx = 0; candidate->packets_rx = *pkt_rcvd; candidate->used = 1; @@ -279,7 +279,7 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { //Candidate was not found in my list, maybe I should add it uint8_t addresult = 0; addresult = etx_add_candidate(candidate_address, - probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); + &(probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET])); if(addresult == 1){ puts("[WARNING] Candidate could not get added"); @@ -296,7 +296,7 @@ void etx_radio(void) { ieee802154_frame_t frame; - msg_init_queue(msg_que, ETX_RCV_BUFFER_SIZE); + msg_init_queue(msg_que, ETX_RCV_QUEUE_SIZE); ipv6_addr_t ll_address; ipv6_addr_t candidate_addr; diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index b2f1312fa8..ed5fc1974d 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -11,16 +11,16 @@ #include "sys/net/sixlowpan/sixlowip.h" -#define ETX_BEACON_STACKSIZE 4500 //TODO debug stacksize, set for production -#define ETX_RADIO_STACKSIZE 4500 //TODO debug stacksize, set for production -#define ETX_UPDT_STACKSIZE 4500 //TODO debug stacksize, set for production +#define ETX_BEACON_STACKSIZE 2000 //TODO debug stacksize, set for production +#define ETX_RADIO_STACKSIZE 2000 //TODO debug stacksize, set for production +#define ETX_UPDT_STACKSIZE 800 //TODO debug stacksize, set for production //[option|length|ipaddr.|packetcount] with up to 15 ipaddr|packetcount pairs // 1 Byte 1 Byte 1 Byte 1 Byte #define ETX_BUF_SIZE (32) -#define ETX_RCV_BUFFER_SIZE (128) +#define ETX_RCV_QUEUE_SIZE (128) //Constants for packets diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index 8000bf7631..af1e4703f7 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -95,7 +95,7 @@ * Default 40, should be enough to get all messages for neighbors. * In my tests, the maximum count of neighbors was around 30-something */ -#define RPL_MAX_CANDIDATE_NEIGHBORS 40 +#define RPL_MAX_CANDIDATE_NEIGHBORS 15//TODO change #define RPL_MAX_PARENTS 5 #define RPL_MAX_ROUTING_ENTRIES 128 #define RPL_ROOT_RANK 1 From 7e54f7ea5f9d7473b5c15d1c7d0b0095d1b75c32 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Sun, 24 Mar 2013 20:03:18 +0100 Subject: [PATCH 31/35] improved handling of etx-messages --- sys/net/sixlowpan/rpl/etx_beaconing.c | 101 +++++++++++++------------- sys/net/sixlowpan/rpl/etx_beaconing.h | 3 +- sys/net/sixlowpan/rpl/rpl_structs.h | 1 + 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index c05bdc5f64..398218c2d9 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -20,17 +20,24 @@ #include "rpl_structs.h" #include "rpl_dodag.h" +//For debugging purposes +#include +//#define ENABLE_DEBUG + +char etx_radio_buf[ETX_RADIO_STACKSIZE] = { 0 }; +char etx_update_buf[ETX_UPDT_STACKSIZE] = { 0 }; + int etx_beacon_pid = 0; int etx_radio_pid = 0; int etx_update_pid = 0; //Buffer -char etx_beacon_buf[ETX_BEACON_STACKSIZE] = { 0 }; -char etx_radio_buf[ETX_RADIO_STACKSIZE] = { 0 }; -char etx_update_buf[ETX_UPDT_STACKSIZE] = { 0 }; - uint8_t etx_send_buf[ETX_BUF_SIZE] = { 0 }; uint8_t etx_rec_buf[ETX_BUF_SIZE] = { 0 }; +char etx_beacon_buf[ETX_BEACON_STACKSIZE] = { 0 }; + +//Message queue for radio +msg_t msg_que[ETX_RCV_QUEUE_SIZE] = { 0 }; /* * The counter for the current 'round'. An ETX beacon is sent every ETX_INTERVAL @@ -39,9 +46,6 @@ uint8_t etx_rec_buf[ETX_BUF_SIZE] = { 0 }; */ static uint8_t rounds = 0; -//Message queue for radio -msg_t msg_que[ETX_RCV_QUEUE_SIZE] = { 0 }; - /* * This could (and should) be done differently, once the RPL implementation * deals with candidate neighbors in another way than just defining that every @@ -78,7 +82,7 @@ void show_candidates(void) { for (candidate = &candidates[0], end = candidates + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; candidate++) { - printf("Candidates Addr:%d\n" + DEBUG("Candidates Addr:%d\n" "\t cur_etx:%f\n" "\t packets_rx:%d\n" "\t used:%d\n", candidate->addr.uint8[ETX_IPV6_LAST_BYTE], @@ -156,7 +160,7 @@ void etx_beacon(void) { etx_p->data[i * ETX_TUPLE_SIZE] = candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; etx_p->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = - candidates[i].packets_rx; + candidates[i].packets_tx; p_length = p_length + ETX_PKT_HDR_LEN; } } @@ -168,7 +172,8 @@ void etx_beacon(void) { //vtimer_usleep(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS); /// TODO once vtimer works as intended, replace the hwtimer here with /// the vtimer. Right now vtimer bugs, so we have hwtimer here. - hwtimer_wait(HWTIMER_TICKS(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS)); + hwtimer_wait( + HWTIMER_TICKS(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS)); jittercorrection = (ETX_MAX_JITTER) - jitter; @@ -199,9 +204,10 @@ double etx_get_metric(ipv6_addr_t * address) { return 0; } -uint8_t etx_add_candidate(ipv6_addr_t * address, uint8_t * pkt_rcvd) { +rpl_candidate_neighbor_t * etx_add_candidate(ipv6_addr_t * address) { + puts("add candidate"); /* - * Pre-Condition: Add etx_add_candidate should only be called when the + * Pre-Condition: etx_add_candidate should only be called when the * candidate is not yet in the list. * Otherwise the candidate will be added a second time, * leading to unknown behavior. @@ -218,11 +224,11 @@ uint8_t etx_add_candidate(ipv6_addr_t * address, uint8_t * pkt_rcvd) { * This shouldn't really happen though, since we have enough * place in the array. * - * Returns if the candidate was added (1) or not (0). + * Returns the pointer to the candidate if it was added, or a NULL-pointer + * otherwise. */ rpl_candidate_neighbor_t * candidate; rpl_candidate_neighbor_t * end; - uint8_t added = 0; for (candidate = &candidates[0], end = candidates + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; @@ -232,16 +238,15 @@ uint8_t etx_add_candidate(ipv6_addr_t * address, uint8_t * pkt_rcvd) { continue; } else { //We still have a free place add the new candidate - candidate->addr = * address; + candidate->addr = *address; candidate->cur_etx = 0; - candidate->packets_rx = *pkt_rcvd; + candidate->packets_tx = 0; + candidate->packets_rx = 0; candidate->used = 1; - - added = 1; - break; + return candidate; } } - return added; + return NULL ; } void etx_handle_beacon(ipv6_addr_t * candidate_address) { @@ -252,42 +257,40 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { etx_probe_t * probe = get_etx_rec_buf(); - //Todo delete once everything works well - printf("ETX beacon package received with following values:\n" + DEBUG("ETX beacon package received with following values:\n" "\tPackage Option:%x\n" "\t Data Length:%u\n" "\tSource Address:%d\n\n", probe->code, probe->length, candidate_address->uint8[ETX_IPV6_LAST_BYTE]); - rpl_candidate_neighbor_t* candidate = NULL; - - for (uint8_t i = 0; i < probe->length / ETX_TUPLE_SIZE; i++) { - //todo delete once everything works well - printf("\tIPv6 short Addr:%u\n" - "\tPackets f. Addr:%u\n\n", probe->data[i * ETX_TUPLE_SIZE], - probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); - - // If i find my address in this probe, update the packet_rx value for - // this candidate, if he is in my candidate list. - if (probe->data[i * ETX_TUPLE_SIZE] - == own_address->uint8[ETX_IPV6_LAST_BYTE]) { - candidate = etx_find_candidate(candidate_address); - if (candidate != NULL ) { - candidate->packets_rx = probe->data[i * ETX_TUPLE_SIZE - + ETX_PKT_REC_OFFSET]; - } else { - //Candidate was not found in my list, maybe I should add it - uint8_t addresult = 0; - addresult = etx_add_candidate(candidate_address, - &(probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET])); - - if(addresult == 1){ - puts("[WARNING] Candidate could not get added"); - } - } + rpl_candidate_neighbor_t* candidate = etx_find_candidate(candidate_address); + if (candidate == NULL ) { + //Candidate was not found in my list, I should add it + candidate = etx_add_candidate(candidate_address); + if (candidate == NULL ) { + puts("[ERROR] Candidate could not get added"); + puts("Increase the constant RPL_MAX_CANDIDATE_NEIGHBORS"); + return; } } + //I have received 1 more packet from this candidate + candidate->packets_tx = candidate->packets_tx + 1; + + // If i find my address in this probe, update the packet_rx value for + // this candidate. + for (uint8_t i = 0; i < probe->length / ETX_TUPLE_SIZE; i++) { + DEBUG("\tIPv6 short Addr:%u\n" + "\tPackets f. Addr:%u\n\n", probe->data[i * ETX_TUPLE_SIZE], + probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); + + if (probe->data[i * ETX_TUPLE_SIZE] + == own_address->uint8[ETX_IPV6_LAST_BYTE]) { + + candidate->packets_rx = probe->data[i * ETX_TUPLE_SIZE + + ETX_PKT_REC_OFFSET]; + } + } } void etx_radio(void) { @@ -364,7 +367,7 @@ void etx_update(void) { candidate->cur_etx = candidate->packets_rx / (double) ETX_ROUNDS; candidate->packets_rx = 0; - printf( + DEBUG( "Updated ETX Metric to %f for candidate used was on %d", candidate->cur_etx, candidate->used); } diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index ed5fc1974d..8dcf3b30b4 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -11,9 +11,10 @@ #include "sys/net/sixlowpan/sixlowip.h" +//4908 is available stack size #define ETX_BEACON_STACKSIZE 2000 //TODO debug stacksize, set for production #define ETX_RADIO_STACKSIZE 2000 //TODO debug stacksize, set for production -#define ETX_UPDT_STACKSIZE 800 //TODO debug stacksize, set for production +#define ETX_UPDT_STACKSIZE 908 //TODO debug stacksize, set for production //[option|length|ipaddr.|packetcount] with up to 15 ipaddr|packetcount pairs diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index af1e4703f7..a71d600514 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -206,6 +206,7 @@ struct rpl_dodag_t; typedef struct rpl_candidate_neighbor_t { ipv6_addr_t addr; //The address of this node + uint8_t packets_tx; //The packets this node has transmitted TO ME uint8_t packets_rx; //The packets this node has received FROM ME double cur_etx; //The currently calculated ETX-value uint8_t used; //The indicator if this node is active or not From b22e80b806e8911dd7c017ef13f7e4174b87a3c3 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Thu, 28 Mar 2013 15:27:30 +0100 Subject: [PATCH 32/35] Fixed ETX calculations --- projects/test_beacon/main.c | 2 + sys/net/sixlowpan/rpl/etx_beaconing.c | 366 ++++++++++++++++++-------- sys/net/sixlowpan/rpl/etx_beaconing.h | 43 +-- sys/net/sixlowpan/rpl/of_mrhof.c | 4 +- sys/net/sixlowpan/rpl/rpl_structs.h | 8 - sys/net/sixlowpan/rpl/trickle.c | 25 +- 6 files changed, 307 insertions(+), 141 deletions(-) diff --git a/projects/test_beacon/main.c b/projects/test_beacon/main.c index eafd39d9d3..aa37ff4e0d 100644 --- a/projects/test_beacon/main.c +++ b/projects/test_beacon/main.c @@ -62,7 +62,9 @@ void table(char *str){ } void candidates(char *str){ + puts("++++++++++++candidates++++++++"); show_candidates(); + puts("++++++++++++end++++++++"); } const shell_command_t shell_commands[] = { diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index 398218c2d9..4837ebdac8 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -17,25 +17,35 @@ #include "sys/net/sixlowpan/sixlowmac.h" #include "sys/net/sixlowpan/ieee802154_frame.h" -#include "rpl_structs.h" #include "rpl_dodag.h" //For debugging purposes +#define ENABLE_DEBUG #include -//#define ENABLE_DEBUG -char etx_radio_buf[ETX_RADIO_STACKSIZE] = { 0 }; -char etx_update_buf[ETX_UPDT_STACKSIZE] = { 0 }; - -int etx_beacon_pid = 0; -int etx_radio_pid = 0; -int etx_update_pid = 0; +//prototytpes +static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate); +static void etx_set_packets_received(void); //Buffer +char etx_beacon_buf[ETX_BEACON_STACKSIZE] = { 0 }; +char etx_radio_buf[ETX_RADIO_STACKSIZE] = { 0 }; +char etx_clock_buf[ETX_CLOCK_STACKSIZE] = { 0 }; + uint8_t etx_send_buf[ETX_BUF_SIZE] = { 0 }; uint8_t etx_rec_buf[ETX_BUF_SIZE] = { 0 }; -char etx_beacon_buf[ETX_BEACON_STACKSIZE] = { 0 }; +//PIDs +int etx_beacon_pid = 0; +int etx_radio_pid = 0; +int etx_clock_pid = 0; + +/* + * xxx If you get a -Wmissing-braces warning here: + * A -Wmissing-braces warning at this point is a gcc-bug! + * Please delete this information once it's fixed + * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + */ //Message queue for radio msg_t msg_que[ETX_RCV_QUEUE_SIZE] = { 0 }; @@ -44,7 +54,12 @@ msg_t msg_que[ETX_RCV_QUEUE_SIZE] = { 0 }; * u-seconds and a node computes the ETX value by comparing the the received * probes vs the expected probes from a neighbor every ETX_ROUND intervals. */ -static uint8_t rounds = 0; +static uint8_t cur_round = 0; + +/* + * If we have not yet reached WINDOW intervals, won't calculate the ETX just yet + */ +static char reached_window = 0; /* * This could (and should) be done differently, once the RPL implementation @@ -54,11 +69,23 @@ static uint8_t rounds = 0; * needing them to be in our parent array, so we have another array here in * which we put all necessary info for up to RPL_MAX_CANDIDATE_NEIGHBORS * candidates. + * + * xxx If you get a -Wmissing-braces warning here: + * A -Wmissing-braces warning at this point is a gcc-bug! + * Please delete this information once it's fixed + * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 */ -//Candidate array for candidate<==>parent matching -//Throws a warning, but this is the correct way to initialize! -static rpl_candidate_neighbor_t candidates[RPL_MAX_CANDIDATE_NEIGHBORS] = { 0 }; +//Candidate array +static etx_neighbor_t candidates[RPL_MAX_CANDIDATE_NEIGHBORS] = { 0 }; +/* + * Each time we send a beacon packet we need to reset some values for the + * current 'round' (a round being the time between each sent beacon packet). + * + * In this time, no packet may be handled, otherwise it could assume values + * from the last round to count for this round. + */ +//mutex_t etx_mutex; //Transceiver command for sending ETX probes transceiver_command_t tcmd; @@ -76,28 +103,33 @@ static etx_probe_t * get_etx_rec_buf(void) { } void show_candidates(void) { - rpl_candidate_neighbor_t * candidate; - rpl_candidate_neighbor_t *end; + etx_neighbor_t * candidate; + etx_neighbor_t *end; for (candidate = &candidates[0], end = candidates + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; candidate++) { - DEBUG("Candidates Addr:%d\n" + if (candidate->used == 0) { + break; + } + printf("Candidates Addr:%d\n" "\t cur_etx:%f\n" "\t packets_rx:%d\n" + "\t packets_tx:%d\n" "\t used:%d\n", candidate->addr.uint8[ETX_IPV6_LAST_BYTE], candidate->cur_etx, candidate->packets_rx, + etx_count_packet_tx(candidate), candidate->used); } } void etx_init_beaconing(ipv6_addr_t * address) { + //mutex_init(&etx_mutex); own_address = address; //set code puts("ETX BEACON INIT"); - etx_send_buf[0] = ETX_BEACON; + etx_send_buf[0] = ETX_PKT_OPTVAL; - thread_print_all(); etx_beacon_pid = thread_create(etx_beacon_buf, ETX_BEACON_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, etx_beacon, "etx_beacon"); @@ -106,16 +138,9 @@ void etx_init_beaconing(ipv6_addr_t * address) { PRIORITY_MAIN - 1, CREATE_STACKTEST, etx_radio, "etx_radio"); - /* - * Maybe this should not be in a seperate thread resource-wise, but the - * motive was to delay beacon-sending as little as possible, as this would - * derail beaconing from the intended ETX_INTERVAL. - */ - - etx_update_pid = thread_create(etx_update_buf, ETX_UPDT_STACKSIZE, + etx_clock_pid = thread_create(etx_clock_buf, ETX_CLOCK_STACKSIZE, PRIORITY_MAIN - 1, CREATE_STACKTEST, - etx_update, "etx_update"); - + etx_clock, "etx_clock"); //register at transceiver transceiver_register(TRANSCEIVER_CC1100, etx_radio_pid); puts("...[DONE]"); @@ -128,61 +153,61 @@ void etx_beacon(void) { * ETX_INTERVAL between the wakeups. It takes the old jittervalue in account * and modifies the time to wait accordingly. */ - etx_probe_t *etx_p = get_etx_send_buf(); - - /* - * The jittercorrection and jitter variables keep usecond values divided - * through 1000 to fit into uint8 variables. - * - * That is why they are multiplied by 1000 when used for hwtimer_wait. - */ - uint8_t jittercorrection = ETX_DEF_JIT_CORRECT; - uint8_t jitter = (uint8_t) (rand() % ETX_JITTER_MOD); - + uint8_t * etx_data = &etx_send_buf[ETX_PKT_DATA]; uint8_t p_length = 0; + /* + * xxx If you get a -Wmissing-braces warning here: + * A -Wmissing-braces warning at this point is a gcc-bug! + * Please delete this information once it's fixed + * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + */ ieee_802154_long_t empty_addr = { 0 }; - while (true) { - - if (rounds == ETX_ROUNDS) { - //calculate the ETX values and update the parents - thread_wakeup(etx_update_pid); - rounds = 1; - } else { - rounds++; + //Build first etx packet + for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + if (candidates[i].used != 0) { + etx_data[i * ETX_TUPLE_SIZE] = + candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; + etx_data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = + etx_count_packet_tx(&candidates[i]); + p_length = p_length + ETX_TUPLE_SIZE; } + } + etx_send_buf[ETX_PKT_LEN] = p_length; + while (true) { + thread_sleep(); + //mutex_lock(&etx_mutex); + send_ieee802154_frame(&empty_addr, &etx_send_buf[0], + etx_send_buf[ETX_PKT_LEN] + ETX_PKT_HDR_LEN, 1); + DEBUG("sent beacon!\n"); + etx_set_packets_received(); + cur_round++; + if (cur_round == ETX_WINDOW) { + if (reached_window != 1) { + //first round is through + reached_window = 1; + } + cur_round = 0; + } + //mutex_unlock(&etx_mutex,0); //Build etx packet p_length = 0; for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { if (candidates[i].used != 0) { - etx_p->data[i * ETX_TUPLE_SIZE] = + etx_data[i * ETX_TUPLE_SIZE] = candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; - etx_p->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = - candidates[i].packets_tx; + etx_data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = + etx_count_packet_tx(&candidates[i]); p_length = p_length + ETX_PKT_HDR_LEN; } } - etx_p->length = p_length; - - send_ieee802154_frame(&empty_addr, &etx_send_buf[0], - get_etx_send_buf()->length + ETX_PKT_HDR_LEN, 1); - puts("sent beacon!"); - //vtimer_usleep(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS); - /// TODO once vtimer works as intended, replace the hwtimer here with - /// the vtimer. Right now vtimer bugs, so we have hwtimer here. - hwtimer_wait( - HWTIMER_TICKS(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS)); - - jittercorrection = (ETX_MAX_JITTER) - jitter; - - //the jitter is a value between 0 and ETX_MAX_JITTER - jitter = (uint8_t) (rand() % ETX_JITTER_MOD); + etx_send_buf[ETX_PKT_LEN] = p_length; } } -rpl_candidate_neighbor_t * etx_find_candidate(ipv6_addr_t * address) { +etx_neighbor_t * etx_find_candidate(ipv6_addr_t * address) { /* * find the candidate with address address and returns it, or returns NULL * if no candidate having this address was found. @@ -196,16 +221,55 @@ rpl_candidate_neighbor_t * etx_find_candidate(ipv6_addr_t * address) { return NULL ; } +void etx_clock(void) { + /* + * Manages the etx_beacon thread to wake up every full second +- jitter + */ + + /* + * The jittercorrection and jitter variables keep usecond values divided + * through 1000 to fit into uint8 variables. + * + * That is why they are multiplied by 1000 when used for hwtimer_wait. + */ + uint8_t jittercorrection = ETX_DEF_JIT_CORRECT; + uint8_t jitter = (uint8_t) (rand() % ETX_JITTER_MOD); + + while (true) { + thread_wakeup(etx_beacon_pid); + + /* + * Vtimer is buggy, but I seem to have no hwtimers left, so using this + * for now. + */ + vtimer_usleep( + ((ETX_INTERVAL - ETX_MAX_JITTER)*MS)+ jittercorrection*MS + jitter*MS - ETX_CLOCK_ADJUST); + + //hwtimer_wait( + // HWTIMER_TICKS(((ETX_INTERVAL - ETX_MAX_JITTER)*MS) + jittercorrection*MS + jitter*MS - ETX_CLOCK_ADJUST)); + + jittercorrection = (ETX_MAX_JITTER) - jitter; + jitter = (uint8_t) (rand() % ETX_JITTER_MOD); + } +} + double etx_get_metric(ipv6_addr_t * address) { - rpl_candidate_neighbor_t * candidate = etx_find_candidate(address); + etx_neighbor_t * candidate = etx_find_candidate(address); if (candidate != NULL ) { - return candidate->packets_rx / (double) ETX_ROUNDS; + if (etx_count_packet_tx(candidate) > 0) { + //this means the current etx_value is not outdated + return candidate->cur_etx; + } else { + //The last time I received a packet is too long ago to give a + //good estimate of the etx value + return 0; + } } return 0; } -rpl_candidate_neighbor_t * etx_add_candidate(ipv6_addr_t * address) { - puts("add candidate"); +etx_neighbor_t * etx_add_candidate(ipv6_addr_t * address) { + DEBUG("add candidate\n"); /* * Pre-Condition: etx_add_candidate should only be called when the * candidate is not yet in the list. @@ -227,8 +291,8 @@ rpl_candidate_neighbor_t * etx_add_candidate(ipv6_addr_t * address) { * Returns the pointer to the candidate if it was added, or a NULL-pointer * otherwise. */ - rpl_candidate_neighbor_t * candidate; - rpl_candidate_neighbor_t * end; + etx_neighbor_t * candidate; + etx_neighbor_t * end; for (candidate = &candidates[0], end = candidates + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; @@ -238,9 +302,9 @@ rpl_candidate_neighbor_t * etx_add_candidate(ipv6_addr_t * address) { continue; } else { //We still have a free place add the new candidate + memset(candidate, 0, sizeof(*candidate)); candidate->addr = *address; candidate->cur_etx = 0; - candidate->packets_tx = 0; candidate->packets_rx = 0; candidate->used = 1; return candidate; @@ -255,15 +319,14 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { * If the candidate address is unknown, try to add it to my struct. */ - etx_probe_t * probe = get_etx_rec_buf(); - - DEBUG("ETX beacon package received with following values:\n" + DEBUG( + "ETX beacon package received with following values:\n" "\tPackage Option:%x\n" "\t Data Length:%u\n" - "\tSource Address:%d\n\n", probe->code, probe->length, + "\tSource Address:%d\n\n", etx_rec_buf[ETX_PKT_OPT], etx_rec_buf[ETX_PKT_LEN], candidate_address->uint8[ETX_IPV6_LAST_BYTE]); - rpl_candidate_neighbor_t* candidate = etx_find_candidate(candidate_address); + etx_neighbor_t* candidate = etx_find_candidate(candidate_address); if (candidate == NULL ) { //Candidate was not found in my list, I should add it candidate = etx_add_candidate(candidate_address); @@ -274,23 +337,30 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { } } - //I have received 1 more packet from this candidate - candidate->packets_tx = candidate->packets_tx + 1; + //I have received 1 packet from this candidate in this round + //This value will be reset by etx_update to 0 + candidate->tx_cur_round = 1; // If i find my address in this probe, update the packet_rx value for // this candidate. - for (uint8_t i = 0; i < probe->length / ETX_TUPLE_SIZE; i++) { - DEBUG("\tIPv6 short Addr:%u\n" - "\tPackets f. Addr:%u\n\n", probe->data[i * ETX_TUPLE_SIZE], - probe->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); + uint8_t datalength = etx_rec_buf[ETX_PKT_LEN]; + uint8_t * rec_data = &etx_rec_buf[ETX_PKT_DATA]; - if (probe->data[i * ETX_TUPLE_SIZE] + for (uint8_t i = 0; i < datalength / ETX_TUPLE_SIZE; i++) { + DEBUG("\tIPv6 short Addr:%u\n" + "\tPackets f. Addr:%u\n\n", rec_data[i * ETX_TUPLE_SIZE], + rec_data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); + + if (rec_data[i * ETX_TUPLE_SIZE] == own_address->uint8[ETX_IPV6_LAST_BYTE]) { - candidate->packets_rx = probe->data[i * ETX_TUPLE_SIZE + candidate->packets_rx = rec_data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]; } } + + //Last, update the ETX value for this candidate + etx_update(candidate); } void etx_radio(void) { @@ -314,7 +384,7 @@ void etx_radio(void) { read_802154_frame(p->data, &frame, p->length); - if (frame.payload[0] == ETX_BEACON) { + if (frame.payload[0] == ETX_PKT_OPTVAL) { //copy to receive buffer memcpy(etx_rec_buf, &frame.payload[0], frame.payload_len); @@ -323,7 +393,9 @@ void etx_radio(void) { //up to 8 bits candidate_addr.uint8[ETX_IPV6_LAST_BYTE] = (uint8_t) p->src; //handle the beacon + //mutex_lock(&etx_mutex); etx_handle_beacon(&candidate_addr); + //mutex_unlock(&etx_mutex,0); } p->processing--; @@ -337,39 +409,105 @@ void etx_radio(void) { } } -void etx_update(void) { +void etx_update(etx_neighbor_t * candidate) { + DEBUG("update!\n"); /* - * Update the current ETX values, then - * reset the received packet count for the candidates. - * - * This thread should never take very long, as it has to be done in less - * than (ETX_INTERVAL - maximum jitter), otherwise the ETX calculation might - * be faulty. TODO delete this once mutexes are in place - * + * Update the current ETX value of a candidate */ - rpl_candidate_neighbor_t * candidate; - rpl_candidate_neighbor_t * end; + double d_f; + double d_r; - while (true) { - //good night - thread_sleep(); - //Wait a tiny bit to allow for the last packet to be processed - hwtimer_wait(HWTIMER_TICKS(200)); + if (reached_window != 1 || candidate == NULL ) { + //We will wait at least ETX_WINDOW beacons until we decide to + //calculate an ETX value, so that we have a good estimate + return; + } - for (candidate = &candidates[0], end = candidates - + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; - candidate++) { + /* + * Calculate d_f (the forward PDR) from ME to this candidate. + */ + d_f = candidate->packets_rx / (double) ETX_WINDOW; - if (candidate->used != 0) { - //update its ETX-metric and packet count TODO mutex this - //TODO probably better to change floating point-math to integer - //based math - candidate->cur_etx = - candidate->packets_rx / (double) ETX_ROUNDS; - candidate->packets_rx = 0; - DEBUG( - "Updated ETX Metric to %f for candidate used was on %d", - candidate->cur_etx, candidate->used); + /* + * Calculate d_r (the backwards PDR) from this candidate to ME + */ + d_r = etx_count_packet_tx(candidate) / (double) ETX_WINDOW; + + /* + * Calculate the current ETX value for my link to this candidate. + */ + if (d_f * d_r != 0) { + candidate->cur_etx = 1 / (d_f * d_r); + } else { + candidate->cur_etx = 0; + } + + DEBUG( + "Estimated ETX Metric is %f for candidate w/ addr %d\n" + "Estimated PDR_forward is %f\n" + "Estimated PDR_backwrd is %f\n" + "\n" + "Received Packets: %d\n" + "Sent Packets : %d\n\n", + candidate->cur_etx, candidate->addr.uint8[ETX_IPV6_LAST_BYTE], + d_f, d_r, candidate->packets_rx, etx_count_packet_tx(candidate)); +} + +static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate) { + /* + * Counts the number of packets that were received for this candidate + * in the last ETX_WINDOW intervals. + */ + puts("counting packets"); + uint8_t pkt_count = 0; + DEBUG("["); + for (uint8_t i = 0; i < ETX_WINDOW; i++) { + if (i != cur_round) { + pkt_count = pkt_count + candidate->packets_tx[i]; +#ifdef ENABLE_DEBUG //so ugly delete TODO + DEBUG("%d",candidate->packets_tx[i]); + if (i < ETX_WINDOW - 1) { + DEBUG(","); + } +#endif + } else { + //Check if I received something for the current round + if (candidate->tx_cur_round == 0) { + //Didn't receive a packet, zero the field and don't add + candidate->packets_tx[i] = 0; +#ifdef ENABLE_DEBUG + DEBUG("%d",candidate->packets_tx[i]); + if (i < ETX_WINDOW - 1) { + DEBUG(","); + } +#endif + } else { + DEBUG("Received packet in ROUND%d!\n", i); + //Add 1 and set field + pkt_count = pkt_count + 1; + candidate->packets_tx[i] = 1; +#ifdef ENABLE_DEBUG + DEBUG("%d",candidate->packets_tx[i]); + if (i < ETX_WINDOW - 1) { + DEBUG(","); + } +#endif + } + } + } + DEBUG("]\n"); + return pkt_count; +} + +static void etx_set_packets_received(void) { + /* + * Set for all candidates if they received a packet this round or not + */ + for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + if (candidates[i].used) { + if (candidates[i].tx_cur_round != 0) { + candidates[i].packets_tx[cur_round] = 1; + candidates[i].tx_cur_round = 0; } } } diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index 8dcf3b30b4..a2dbfd751f 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -12,9 +12,9 @@ #include "sys/net/sixlowpan/sixlowip.h" //4908 is available stack size -#define ETX_BEACON_STACKSIZE 2000 //TODO debug stacksize, set for production -#define ETX_RADIO_STACKSIZE 2000 //TODO debug stacksize, set for production -#define ETX_UPDT_STACKSIZE 908 //TODO debug stacksize, set for production +#define ETX_BEACON_STACKSIZE 4500 //TODO debug stacksize, set for production +#define ETX_RADIO_STACKSIZE 4500 //TODO debug stacksize, set for production +#define ETX_CLOCK_STACKSIZE 4500 //TODO debug stacksize, set for production //[option|length|ipaddr.|packetcount] with up to 15 ipaddr|packetcount pairs @@ -25,8 +25,6 @@ //Constants for packets -//ETX beaconing type (XXX ATTENTION! this is non-standard) -#define ETX_BEACON 0x20//Non-standard way of saying this is an etx-pkt. //ETX Interval parameters #define MS 1000 @@ -39,21 +37,14 @@ * and 5 (For ETX_MAX_JITTER) unless those values are adjusted too. */ #define ETX_INTERVAL (1000) -#define ETX_ROUNDS (10) //10 is the default value -#define ETX_PKT_HDR_LEN (2) //Option type + Length (1 Byte each) +#define ETX_WINDOW (10) //10 is the default value #define ETX_TUPLE_SIZE (2) //1 Byte for Addr, 1 Byte for packets rec. #define ETX_PKT_REC_OFFSET (ETX_TUPLE_SIZE - 1) //Offset in a tuple of (addr,pkt_rec), will always be the last byte #define ETX_IPV6_LAST_BYTE (15) //The last byte for an ipv6 address #define ETX_MAX_JITTER (ETX_INTERVAL / 5) //The default value is 20% of ETX_INTERVAL #define ETX_JITTER_MOD (ETX_MAX_JITTER + 1) //The modulo value for jitter computation #define ETX_DEF_JIT_CORRECT (ETX_MAX_JITTER / 2) //Default Jitter correction value (normally ETX_MAX_JITTER / 2) - -//prototypes -void etx_init_beaconing(ipv6_addr_t * address); -void etx_beacon(void); -double etx_get_metric(ipv6_addr_t * address); -void etx_update(void); -void etx_radio(void); +#define ETX_CLOCK_ADJUST (52500) //Adjustment for clockthread computations to stay close/near ETX_INTERVAL /* * The ETX beaconing packet consists of: @@ -76,11 +67,33 @@ void etx_radio(void); * If the length of this packet says 0, it has received no other beaconing * packets itself so far. */ -typedef struct __attribute__((packed)) { +typedef struct __attribute__((packed)) etx_probe_t{ uint8_t code; uint8_t length; uint8_t* data; } etx_probe_t; +typedef struct etx_neighbor_t { + ipv6_addr_t addr; //The address of this node + uint8_t tx_cur_round; //The indicator for receiving a packet from this candidate this round + uint8_t packets_tx[10]; //The packets this node has transmitted TO ME + uint8_t packets_rx; //The packets this node has received FROM ME + double cur_etx; //The currently calculated ETX-value + uint8_t used; //The indicator if this node is active or not +} etx_neighbor_t; + +//prototypes +void etx_init_beaconing(ipv6_addr_t * address); +void etx_beacon(void); +void etx_clock(void); +double etx_get_metric(ipv6_addr_t * address); +void etx_update(etx_neighbor_t * neighbor); +void etx_radio(void); + +#define ETX_PKT_OPT (0) //Position of Option-Type-Byte +#define ETX_PKT_OPTVAL (0x20) //Non-standard way of saying this is an ETX-Packet. +#define ETX_PKT_LEN (1) //Position of Length-Byte +#define ETX_PKT_HDR_LEN (2) //Option type + Length (1 Byte each) +#define ETX_PKT_DATA (2) //Begin of Data Bytes #endif /* ETX_BEACONING_H_ */ diff --git a/sys/net/sixlowpan/rpl/of_mrhof.c b/sys/net/sixlowpan/rpl/of_mrhof.c index c76082c892..1eeac0d8dc 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.c +++ b/sys/net/sixlowpan/rpl/of_mrhof.c @@ -2,6 +2,8 @@ #include #include "of_mrhof.h" +#include "etx_beaconing.h" + // Function Prototypes static uint16_t calc_rank(rpl_parent_t *, uint16_t); static rpl_parent_t *which_parent(rpl_parent_t *, rpl_parent_t *); @@ -39,7 +41,7 @@ static uint16_t calc_path_cost(rpl_parent_t * parent) { return DEFAULT_MIN_HOP_RANK_INCREASE; } - double etx_value = etx_get_metric(parent->addr); + double etx_value = etx_get_metric(&(parent->addr)); if (etx_value != 0) { /* * (ETX_for_link_to_neighbor * 128) + Rank_of_that_neighbor diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index a71d600514..94851bd17c 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -204,14 +204,6 @@ typedef struct __attribute__((packed)) rpl_opt_transit_t { struct rpl_dodag_t; -typedef struct rpl_candidate_neighbor_t { - ipv6_addr_t addr; //The address of this node - uint8_t packets_tx; //The packets this node has transmitted TO ME - uint8_t packets_rx; //The packets this node has received FROM ME - double cur_etx; //The currently calculated ETX-value - uint8_t used; //The indicator if this node is active or not -} rpl_candidate_neighbor_t; - typedef struct rpl_parent_t { ipv6_addr_t addr; uint16_t rank; diff --git a/sys/net/sixlowpan/rpl/trickle.c b/sys/net/sixlowpan/rpl/trickle.c index eca3eb66fc..8a7d3d6b3c 100644 --- a/sys/net/sixlowpan/rpl/trickle.c +++ b/sys/net/sixlowpan/rpl/trickle.c @@ -5,9 +5,10 @@ #include "trickle.h" #include "sys/net/sixlowpan/rpl/rpl.h" -char timer_over_buf[TRICKLE_TIMER_STACKSIZE]; -char interval_over_buf[TRICKLE_INTERVAL_STACKSIZE]; -char dao_delay_over_buf[DAO_DELAY_STACKSIZE]; +//TODO in pointer umwandeln, speicher mit malloc holen +char * timer_over_buf; +char * interval_over_buf; +char * dao_delay_over_buf; char routing_table_buf[RT_STACKSIZE]; int timer_over_pid; int interval_over_pid; @@ -50,6 +51,24 @@ void reset_trickletimer(void){ } void init_trickle(void){ + puts("trickle init!"); + //malloc thread stacks + timer_over_buf = malloc(TRICKLE_TIMER_STACKSIZE*sizeof(char)); + if(timer_over_buf == NULL){ + puts("[ERROR] Could not allocate enough memory for timer_over_buf!"); + return; + } + interval_over_buf = malloc(TRICKLE_INTERVAL_STACKSIZE*sizeof(char)); + if(interval_over_buf == NULL){ + puts("[ERROR] Could not allocate enough memory for interval_over_buf!"); + return; + } + dao_delay_over_buf = malloc(DAO_DELAY_STACKSIZE*sizeof(char)); + if(dao_delay_over_buf == NULL){ + puts("[ERROR] Could not allocate enough memory for interval_over_buf!"); + return; + } + //Create threads ack_received = true; timer_over_pid = thread_create(timer_over_buf, TRICKLE_TIMER_STACKSIZE, From 60c594b8527eaff048b29f9346021a0c20fd9cb1 Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Thu, 28 Mar 2013 17:11:12 +0100 Subject: [PATCH 33/35] Deleted ETX structs in rpl_structs and added them in etx_beaconing.h changed packet size sent to be fix and not variable changed some array sizes if debug is enabled --- sys/net/sixlowpan/rpl/etx_beaconing.c | 70 ++++++++++++++------------- sys/net/sixlowpan/rpl/etx_beaconing.h | 35 +++++++++++--- sys/net/sixlowpan/rpl/rpl_structs.h | 5 -- 3 files changed, 64 insertions(+), 46 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index 4837ebdac8..6bbf029120 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -17,15 +17,11 @@ #include "sys/net/sixlowpan/sixlowmac.h" #include "sys/net/sixlowpan/ieee802154_frame.h" -#include "rpl_dodag.h" - -//For debugging purposes -#define ENABLE_DEBUG -#include //prototytpes static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate); static void etx_set_packets_received(void); +static bool etx_equal_id(ipv6_addr_t *id1, ipv6_addr_t *id2); //Buffer char etx_beacon_buf[ETX_BEACON_STACKSIZE] = { 0 }; @@ -67,7 +63,7 @@ static char reached_window = 0; * possible neighbor we hear from is a parent. * Right now, we need to keep track of the ETX values of other nodes without * needing them to be in our parent array, so we have another array here in - * which we put all necessary info for up to RPL_MAX_CANDIDATE_NEIGHBORS + * which we put all necessary info for up to ETX_MAX_CANDIDATE_NEIHGBORS * candidates. * * xxx If you get a -Wmissing-braces warning here: @@ -76,7 +72,7 @@ static char reached_window = 0; * See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 */ //Candidate array -static etx_neighbor_t candidates[RPL_MAX_CANDIDATE_NEIGHBORS] = { 0 }; +static etx_neighbor_t candidates[ETX_MAX_CANDIDATE_NEIGHBORS] = { 0 }; /* * Each time we send a beacon packet we need to reset some values for the @@ -95,10 +91,10 @@ msg_t mesg; //RPL-address static ipv6_addr_t * own_address; -static etx_probe_t * get_etx_send_buf(void) { +static etx_probe_t * etx_get_send_buf(void) { return ((etx_probe_t *) &(etx_send_buf[0])); } -static etx_probe_t * get_etx_rec_buf(void) { +static etx_probe_t * etx_get_rec_buf(void) { return ((etx_probe_t *) &(etx_rec_buf[0])); } @@ -107,7 +103,7 @@ void show_candidates(void) { etx_neighbor_t *end; for (candidate = &candidates[0], end = candidates - + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; + + ETX_MAX_CANDIDATE_NEIGHBORS; candidate < end; candidate++) { if (candidate->used == 0) { break; @@ -153,7 +149,7 @@ void etx_beacon(void) { * ETX_INTERVAL between the wakeups. It takes the old jittervalue in account * and modifies the time to wait accordingly. */ - uint8_t * etx_data = &etx_send_buf[ETX_PKT_DATA]; + etx_probe_t * packet = etx_get_send_buf(); uint8_t p_length = 0; /* @@ -165,22 +161,22 @@ void etx_beacon(void) { ieee_802154_long_t empty_addr = { 0 }; //Build first etx packet - for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + for (uint8_t i = 0; i < ETX_MAX_CANDIDATE_NEIGHBORS; i++) { if (candidates[i].used != 0) { - etx_data[i * ETX_TUPLE_SIZE] = + packet->data[i * ETX_TUPLE_SIZE] = candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; - etx_data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = + packet->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = etx_count_packet_tx(&candidates[i]); p_length = p_length + ETX_TUPLE_SIZE; } } - etx_send_buf[ETX_PKT_LEN] = p_length; + packet->length = p_length; while (true) { thread_sleep(); //mutex_lock(&etx_mutex); send_ieee802154_frame(&empty_addr, &etx_send_buf[0], - etx_send_buf[ETX_PKT_LEN] + ETX_PKT_HDR_LEN, 1); + ETX_DATA_MAXLEN+ETX_PKT_HDR_LEN, 1); DEBUG("sent beacon!\n"); etx_set_packets_received(); cur_round++; @@ -194,16 +190,16 @@ void etx_beacon(void) { //mutex_unlock(&etx_mutex,0); //Build etx packet p_length = 0; - for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + for (uint8_t i = 0; i < ETX_MAX_CANDIDATE_NEIGHBORS; i++) { if (candidates[i].used != 0) { - etx_data[i * ETX_TUPLE_SIZE] = + packet->data[i * ETX_TUPLE_SIZE] = candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; - etx_data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = + packet->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = etx_count_packet_tx(&candidates[i]); p_length = p_length + ETX_PKT_HDR_LEN; } } - etx_send_buf[ETX_PKT_LEN] = p_length; + packet->length = p_length; } } @@ -212,9 +208,9 @@ etx_neighbor_t * etx_find_candidate(ipv6_addr_t * address) { * find the candidate with address address and returns it, or returns NULL * if no candidate having this address was found. */ - for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + for (uint8_t i = 0; i < ETX_MAX_CANDIDATE_NEIGHBORS; i++) { if (candidates[i].used - && (rpl_equal_id(&candidates[i].addr, address))) { + && (etx_equal_id(&candidates[i].addr, address))) { return &candidates[i]; } } @@ -295,7 +291,7 @@ etx_neighbor_t * etx_add_candidate(ipv6_addr_t * address) { etx_neighbor_t * end; for (candidate = &candidates[0], end = candidates - + RPL_MAX_CANDIDATE_NEIGHBORS; candidate < end; + + ETX_MAX_CANDIDATE_NEIGHBORS; candidate < end; candidate++) { if (candidate->used) { //skip @@ -332,7 +328,7 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { candidate = etx_add_candidate(candidate_address); if (candidate == NULL ) { puts("[ERROR] Candidate could not get added"); - puts("Increase the constant RPL_MAX_CANDIDATE_NEIGHBORS"); + puts("Increase the constant ETX_MAX_CANDIDATE_NEIHGBORS"); return; } } @@ -343,18 +339,17 @@ void etx_handle_beacon(ipv6_addr_t * candidate_address) { // If i find my address in this probe, update the packet_rx value for // this candidate. - uint8_t datalength = etx_rec_buf[ETX_PKT_LEN]; - uint8_t * rec_data = &etx_rec_buf[ETX_PKT_DATA]; + etx_probe_t * rec_pkt = etx_get_rec_buf(); - for (uint8_t i = 0; i < datalength / ETX_TUPLE_SIZE; i++) { + for (uint8_t i = 0; i < rec_pkt->length / ETX_TUPLE_SIZE; i++) { DEBUG("\tIPv6 short Addr:%u\n" - "\tPackets f. Addr:%u\n\n", rec_data[i * ETX_TUPLE_SIZE], - rec_data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); + "\tPackets f. Addr:%u\n\n", rec_pkt->data[i * ETX_TUPLE_SIZE], + rec_pkt->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]); - if (rec_data[i * ETX_TUPLE_SIZE] + if (rec_pkt->data[i * ETX_TUPLE_SIZE] == own_address->uint8[ETX_IPV6_LAST_BYTE]) { - candidate->packets_rx = rec_data[i * ETX_TUPLE_SIZE + candidate->packets_rx = rec_pkt->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]; } } @@ -482,7 +477,6 @@ static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate) { } #endif } else { - DEBUG("Received packet in ROUND%d!\n", i); //Add 1 and set field pkt_count = pkt_count + 1; candidate->packets_tx[i] = 1; @@ -503,7 +497,7 @@ static void etx_set_packets_received(void) { /* * Set for all candidates if they received a packet this round or not */ - for (uint8_t i = 0; i < RPL_MAX_CANDIDATE_NEIGHBORS; i++) { + for (uint8_t i = 0; i < ETX_MAX_CANDIDATE_NEIGHBORS; i++) { if (candidates[i].used) { if (candidates[i].tx_cur_round != 0) { candidates[i].packets_tx[cur_round] = 1; @@ -512,3 +506,13 @@ static void etx_set_packets_received(void) { } } } + +bool etx_equal_id(ipv6_addr_t *id1, ipv6_addr_t *id2){ + for(uint8_t i=0;i<4;i++){ + if(id1->uint32[i] != id2->uint32[i]){ + return false; + } + } + return true; + +} diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index a2dbfd751f..da94fa101f 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -11,11 +11,19 @@ #include "sys/net/sixlowpan/sixlowip.h" -//4908 is available stack size -#define ETX_BEACON_STACKSIZE 4500 //TODO debug stacksize, set for production -#define ETX_RADIO_STACKSIZE 4500 //TODO debug stacksize, set for production -#define ETX_CLOCK_STACKSIZE 4500 //TODO debug stacksize, set for production +//For debugging purposes +#define ENABLE_DEBUG +#include +#ifdef ENABLE_DEBUG + #define ETX_BEACON_STACKSIZE 4500 + #define ETX_RADIO_STACKSIZE 4500 + #define ETX_CLOCK_STACKSIZE 500 +#else + #define ETX_BEACON_STACKSIZE 2500 //TODO optimize, maybe 2000 is enough + #define ETX_RADIO_STACKSIZE 2500 //TODO optimize, maybe 2000 is enough + #define ETX_CLOCK_STACKSIZE 500 //TODO optimize, maybe 250 is enough +#endif //[option|length|ipaddr.|packetcount] with up to 15 ipaddr|packetcount pairs // 1 Byte 1 Byte 1 Byte 1 Byte @@ -23,9 +31,15 @@ #define ETX_RCV_QUEUE_SIZE (128) -//Constants for packets - - +/* + * Default 40, should be enough to get all messages for neighbors. + * In my tests, the maximum count of neighbors was around 30-something + */ +#ifdef ENABLE_DEBUG + #define ETX_MAX_CANDIDATE_NEIGHBORS 15 //Stacksizes are huge in debug mode, so memory is rare +#else + #define ETX_MAX_CANDIDATE_NEIGHBORS 40 +#endif //ETX Interval parameters #define MS 1000 @@ -66,11 +80,15 @@ * * If the length of this packet says 0, it has received no other beaconing * packets itself so far. + * + * The packet is always 32bytes long, but may contain varying amounts of + * information. + * The information processed shall not exceed the value set in Option Length. */ typedef struct __attribute__((packed)) etx_probe_t{ uint8_t code; uint8_t length; - uint8_t* data; + uint8_t data[30]; } etx_probe_t; typedef struct etx_neighbor_t { @@ -93,6 +111,7 @@ void etx_radio(void); #define ETX_PKT_OPT (0) //Position of Option-Type-Byte #define ETX_PKT_OPTVAL (0x20) //Non-standard way of saying this is an ETX-Packet. #define ETX_PKT_LEN (1) //Position of Length-Byte +#define ETX_DATA_MAXLEN (30) //max length of the data #define ETX_PKT_HDR_LEN (2) //Option type + Length (1 Byte each) #define ETX_PKT_DATA (2) //Begin of Data Bytes diff --git a/sys/net/sixlowpan/rpl/rpl_structs.h b/sys/net/sixlowpan/rpl/rpl_structs.h index 94851bd17c..59a5d5694c 100644 --- a/sys/net/sixlowpan/rpl/rpl_structs.h +++ b/sys/net/sixlowpan/rpl/rpl_structs.h @@ -91,11 +91,6 @@ #define NUMBER_IMPLEMENTED_OFS 2 #define RPL_MAX_DODAGS 3 #define RPL_MAX_INSTANCES 1 -/* - * Default 40, should be enough to get all messages for neighbors. - * In my tests, the maximum count of neighbors was around 30-something - */ -#define RPL_MAX_CANDIDATE_NEIGHBORS 15//TODO change #define RPL_MAX_PARENTS 5 #define RPL_MAX_ROUTING_ENTRIES 128 #define RPL_ROOT_RANK 1 From 1fd9325d8c6dbe2cffbd071018d8eee33c83405e Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Thu, 28 Mar 2013 17:40:01 +0100 Subject: [PATCH 34/35] switched DEBUG mode off --- sys/net/sixlowpan/rpl/etx_beaconing.c | 2 +- sys/net/sixlowpan/rpl/etx_beaconing.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index 6bbf029120..9773156546 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -453,7 +453,7 @@ static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate) { * Counts the number of packets that were received for this candidate * in the last ETX_WINDOW intervals. */ - puts("counting packets"); + DEBUG("counting packets"); uint8_t pkt_count = 0; DEBUG("["); for (uint8_t i = 0; i < ETX_WINDOW; i++) { diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index da94fa101f..4baccb6aa5 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -12,7 +12,7 @@ #include "sys/net/sixlowpan/sixlowip.h" //For debugging purposes -#define ENABLE_DEBUG +//#define ENABLE_DEBUG #include #ifdef ENABLE_DEBUG From d9c9f38c61c7075fd2d93a6c256e55d430e1511c Mon Sep 17 00:00:00 2001 From: Stephan Arndt Date: Fri, 29 Mar 2013 13:41:48 +0100 Subject: [PATCH 35/35] integrated ETX calculation with RPL, rpl messages seem to not get handled very often --- sys/net/sixlowpan/rpl/etx_beaconing.c | 54 +++++++++++---------------- sys/net/sixlowpan/rpl/etx_beaconing.h | 5 ++- sys/net/sixlowpan/rpl/of_mrhof.c | 6 ++- sys/net/sixlowpan/rpl/of_mrhof.h | 5 +++ sys/net/sixlowpan/rpl/rpl.c | 20 +++++++--- sys/net/sixlowpan/rpl/trickle.c | 8 ++-- sys/net/sixlowpan/sixlowmac.c | 2 +- 7 files changed, 52 insertions(+), 48 deletions(-) diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.c b/sys/net/sixlowpan/rpl/etx_beaconing.c index 9773156546..f6af4653b9 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.c +++ b/sys/net/sixlowpan/rpl/etx_beaconing.c @@ -81,7 +81,7 @@ static etx_neighbor_t candidates[ETX_MAX_CANDIDATE_NEIGHBORS] = { 0 }; * In this time, no packet may be handled, otherwise it could assume values * from the last round to count for this round. */ -//mutex_t etx_mutex; +mutex_t etx_mutex; //Transceiver command for sending ETX probes transceiver_command_t tcmd; @@ -120,7 +120,7 @@ void show_candidates(void) { } void etx_init_beaconing(ipv6_addr_t * address) { - //mutex_init(&etx_mutex); + mutex_init(&etx_mutex); own_address = address; //set code puts("ETX BEACON INIT"); @@ -160,21 +160,21 @@ void etx_beacon(void) { */ ieee_802154_long_t empty_addr = { 0 }; - //Build first etx packet - for (uint8_t i = 0; i < ETX_MAX_CANDIDATE_NEIGHBORS; i++) { - if (candidates[i].used != 0) { - packet->data[i * ETX_TUPLE_SIZE] = - candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; - packet->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = - etx_count_packet_tx(&candidates[i]); - p_length = p_length + ETX_TUPLE_SIZE; - } - } - packet->length = p_length; - while (true) { thread_sleep(); - //mutex_lock(&etx_mutex); + mutex_lock(&etx_mutex); + //Build etx packet + p_length = 0; + for (uint8_t i = 0; i < ETX_BEST_CANDIDATES; i++) { + if (candidates[i].used != 0) { + packet->data[i * ETX_TUPLE_SIZE] = + candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; + packet->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = + etx_count_packet_tx(&candidates[i]); + p_length = p_length + ETX_PKT_HDR_LEN; + } + } + packet->length = p_length; send_ieee802154_frame(&empty_addr, &etx_send_buf[0], ETX_DATA_MAXLEN+ETX_PKT_HDR_LEN, 1); DEBUG("sent beacon!\n"); @@ -187,19 +187,7 @@ void etx_beacon(void) { } cur_round = 0; } - //mutex_unlock(&etx_mutex,0); - //Build etx packet - p_length = 0; - for (uint8_t i = 0; i < ETX_MAX_CANDIDATE_NEIGHBORS; i++) { - if (candidates[i].used != 0) { - packet->data[i * ETX_TUPLE_SIZE] = - candidates[i].addr.uint8[ETX_IPV6_LAST_BYTE]; - packet->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET] = - etx_count_packet_tx(&candidates[i]); - p_length = p_length + ETX_PKT_HDR_LEN; - } - } - packet->length = p_length; + mutex_unlock(&etx_mutex,0); } } @@ -388,9 +376,9 @@ void etx_radio(void) { //up to 8 bits candidate_addr.uint8[ETX_IPV6_LAST_BYTE] = (uint8_t) p->src; //handle the beacon - //mutex_lock(&etx_mutex); + mutex_lock(&etx_mutex); etx_handle_beacon(&candidate_addr); - //mutex_unlock(&etx_mutex,0); + mutex_unlock(&etx_mutex,1); } p->processing--; @@ -459,7 +447,7 @@ static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate) { for (uint8_t i = 0; i < ETX_WINDOW; i++) { if (i != cur_round) { pkt_count = pkt_count + candidate->packets_tx[i]; -#ifdef ENABLE_DEBUG //so ugly delete TODO +#ifdef ENABLE_DEBUG DEBUG("%d",candidate->packets_tx[i]); if (i < ETX_WINDOW - 1) { DEBUG(","); @@ -471,7 +459,7 @@ static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate) { //Didn't receive a packet, zero the field and don't add candidate->packets_tx[i] = 0; #ifdef ENABLE_DEBUG - DEBUG("%d",candidate->packets_tx[i]); + DEBUG("%d!",candidate->packets_tx[i]); if (i < ETX_WINDOW - 1) { DEBUG(","); } @@ -481,7 +469,7 @@ static uint8_t etx_count_packet_tx(etx_neighbor_t * candidate) { pkt_count = pkt_count + 1; candidate->packets_tx[i] = 1; #ifdef ENABLE_DEBUG - DEBUG("%d",candidate->packets_tx[i]); + DEBUG("%d!",candidate->packets_tx[i]); if (i < ETX_WINDOW - 1) { DEBUG(","); } diff --git a/sys/net/sixlowpan/rpl/etx_beaconing.h b/sys/net/sixlowpan/rpl/etx_beaconing.h index 4baccb6aa5..611b45de66 100644 --- a/sys/net/sixlowpan/rpl/etx_beaconing.h +++ b/sys/net/sixlowpan/rpl/etx_beaconing.h @@ -12,7 +12,7 @@ #include "sys/net/sixlowpan/sixlowip.h" //For debugging purposes -//#define ENABLE_DEBUG +#define ENABLE_DEBUG #include #ifdef ENABLE_DEBUG @@ -52,6 +52,7 @@ */ #define ETX_INTERVAL (1000) #define ETX_WINDOW (10) //10 is the default value +#define ETX_BEST_CANDIDATES (15) //Sent only 15 candidates in a beaconing packet #define ETX_TUPLE_SIZE (2) //1 Byte for Addr, 1 Byte for packets rec. #define ETX_PKT_REC_OFFSET (ETX_TUPLE_SIZE - 1) //Offset in a tuple of (addr,pkt_rec), will always be the last byte #define ETX_IPV6_LAST_BYTE (15) //The last byte for an ipv6 address @@ -94,7 +95,7 @@ typedef struct __attribute__((packed)) etx_probe_t{ typedef struct etx_neighbor_t { ipv6_addr_t addr; //The address of this node uint8_t tx_cur_round; //The indicator for receiving a packet from this candidate this round - uint8_t packets_tx[10]; //The packets this node has transmitted TO ME + uint8_t packets_tx[ETX_WINDOW]; //The packets this node has transmitted TO ME uint8_t packets_rx; //The packets this node has received FROM ME double cur_etx; //The currently calculated ETX-value uint8_t used; //The indicator if this node is active or not diff --git a/sys/net/sixlowpan/rpl/of_mrhof.c b/sys/net/sixlowpan/rpl/of_mrhof.c index 1eeac0d8dc..66f04f7c6a 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.c +++ b/sys/net/sixlowpan/rpl/of_mrhof.c @@ -31,17 +31,19 @@ void reset(rpl_dodag_t *dodag) { } static uint16_t calc_path_cost(rpl_parent_t * parent) { + puts("calc_pathcost"); /* * Calculates the path cost through the parent, for now, only for ETX */ if (parent == NULL ) { // Shouldn't ever happen since this function is supposed to be always // run with a parent. If it does happen, we can assume a root called it. - printf("[WARNING] calc_path_cost called without parent!"); + puts("[WARNING] calc_path_cost called without parent!"); return DEFAULT_MIN_HOP_RANK_INCREASE; } double etx_value = etx_get_metric(&(parent->addr)); + printf("Metric for parent returned: %f", etx_value); if (etx_value != 0) { /* * (ETX_for_link_to_neighbor * 128) + Rank_of_that_neighbor @@ -74,6 +76,7 @@ static uint16_t calc_path_cost(rpl_parent_t * parent) { } static uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank) { + puts("calc_rank"); /* * Return the rank for this node. * @@ -117,6 +120,7 @@ static uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank) { } static rpl_parent_t * which_parent(rpl_parent_t * p1, rpl_parent_t * p2) { + puts("which_parent"); /* * Return the parent with the lowest path cost. * Before returning any of the two given parents, make sure that a switch is diff --git a/sys/net/sixlowpan/rpl/of_mrhof.h b/sys/net/sixlowpan/rpl/of_mrhof.h index b15f31e855..214353bc7b 100644 --- a/sys/net/sixlowpan/rpl/of_mrhof.h +++ b/sys/net/sixlowpan/rpl/of_mrhof.h @@ -1,3 +1,8 @@ +//For debugging purposes +#define ENABLE_DEBUG +#include + + #include "rpl_structs.h" /* diff --git a/sys/net/sixlowpan/rpl/rpl.c b/sys/net/sixlowpan/rpl/rpl.c index 9671a37ee6..566768fc86 100644 --- a/sys/net/sixlowpan/rpl/rpl.c +++ b/sys/net/sixlowpan/rpl/rpl.c @@ -158,7 +158,10 @@ uint8_t rpl_init(transceiver_type_t trans, uint16_t rpl_address){ //INSERT NEW OBJECTIVE FUNCTIONS HERE objective_functions[0] = rpl_get_of0(); + puts("OF0 added.");//todo del objective_functions[1] = rpl_get_of_mrhof(); + puts("OF_MRHOF added.");//todo del + sixlowpan_init(trans,rpl_address,0); //Wir benötigen einen Link Local prefix, um unsere entsprechende Addresse im Netz abzufragen @@ -206,7 +209,7 @@ void rpl_init_root(){ dodag->version = RPL_COUNTER_INIT; dodag->grounded = RPL_GROUNDED; dodag->node_status = (uint8_t) ROOT_NODE; - dodag->my_rank = ROOT_RANK; //TODO change this, according to spec. + dodag->my_rank = ROOT_RANK; dodag->joined = 1; dodag->my_preferred_parent = NULL; } @@ -222,7 +225,7 @@ void rpl_init_root(){ void send_DIO(ipv6_addr_t* destination){ - //puts("\nSEND DIO"); + puts("=================SEND DIO=================");//TODO comment out mutex_lock(&rpl_send_mutex); rpl_dodag_t * mydodag; icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); @@ -277,7 +280,7 @@ void send_DIO(ipv6_addr_t* destination){ } void send_DIS(ipv6_addr_t *destination){ - //puts("Send DIS"); + puts("=================Send DIS================="); mutex_lock(&rpl_send_mutex); icmp_send_buf = get_rpl_send_icmpv6_buf(ipv6_ext_hdr_len); @@ -298,6 +301,7 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, if(i_am_root){ return; } + puts("=================Send DAO=================");//todo del mutex_lock(&rpl_send_mutex); rpl_dodag_t * my_dodag; my_dodag = rpl_get_my_dodag(); @@ -382,7 +386,7 @@ void send_DAO(ipv6_addr_t *destination, uint8_t lifetime, bool default_lifetime, } void send_DAO_ACK(ipv6_addr_t *destination){ - //puts("Send DAO_ACK to"); + puts("=================Send DAO_ACK to================="); ipv6_print_addr(destination); rpl_dodag_t * my_dodag; my_dodag = rpl_get_my_dodag(); @@ -410,7 +414,7 @@ void send_DAO_ACK(ipv6_addr_t *destination){ } void rpl_process(void){ - + puts("rpl process here!");//todo del msg_t m_recv; msg_init_queue(msg_queue, RPL_PKT_RECV_BUF_SIZE); @@ -425,24 +429,28 @@ void rpl_process(void){ memcpy(&rpl_buffer,ipv6_buf,ipv6_buf->length+IPV6_HDR_LEN); switch(*code) { case(ICMP_CODE_DIS):{ + puts("=================processing DIS!=================");//todo del recv_rpl_dis(); mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); break; } case(ICMP_CODE_DIO):{ + puts("=================processing DIO!=================");//todo del recv_rpl_dio(); mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); break; } case(ICMP_CODE_DAO):{ + puts("=================processing DAO!=================");//todo del recv_rpl_dao(); mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); break; } case(ICMP_CODE_DAO_ACK):{ + puts("=================processing DAOACK!=================");//todo del recv_rpl_dao_ack(); mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); @@ -451,7 +459,7 @@ void rpl_process(void){ default: mutex_unlock(&rpl_recv_mutex, 0); //mutex_unlock(&rpl_send_mutex, 0); - puts("default unlock"); + puts("=================default unlock================="); break; } } diff --git a/sys/net/sixlowpan/rpl/trickle.c b/sys/net/sixlowpan/rpl/trickle.c index 8a7d3d6b3c..5a70e0107e 100644 --- a/sys/net/sixlowpan/rpl/trickle.c +++ b/sys/net/sixlowpan/rpl/trickle.c @@ -51,19 +51,17 @@ void reset_trickletimer(void){ } void init_trickle(void){ - puts("trickle init!"); - //malloc thread stacks - timer_over_buf = malloc(TRICKLE_TIMER_STACKSIZE*sizeof(char)); + timer_over_buf = calloc(TRICKLE_TIMER_STACKSIZE,sizeof(char)); if(timer_over_buf == NULL){ puts("[ERROR] Could not allocate enough memory for timer_over_buf!"); return; } - interval_over_buf = malloc(TRICKLE_INTERVAL_STACKSIZE*sizeof(char)); + interval_over_buf = calloc(TRICKLE_INTERVAL_STACKSIZE,sizeof(char)); if(interval_over_buf == NULL){ puts("[ERROR] Could not allocate enough memory for interval_over_buf!"); return; } - dao_delay_over_buf = malloc(DAO_DELAY_STACKSIZE*sizeof(char)); + dao_delay_over_buf = calloc(DAO_DELAY_STACKSIZE,sizeof(char)); if(dao_delay_over_buf == NULL){ puts("[ERROR] Could not allocate enough memory for interval_over_buf!"); return; diff --git a/sys/net/sixlowpan/sixlowmac.c b/sys/net/sixlowpan/sixlowmac.c index e000f08695..d0ed5030d1 100644 --- a/sys/net/sixlowpan/sixlowmac.c +++ b/sys/net/sixlowpan/sixlowmac.c @@ -191,7 +191,7 @@ void send_ieee802154_frame(ieee_802154_long_t *addr, uint8_t *payload, p.data = buf; msg_send_receive(&mesg, &transceiver_rsp, transceiver_pid); - printf("%s, %u: %lu\n", __FILE__, __LINE__, transceiver_rsp.content.value); + //printf("%s, %u: %lu\n", __FILE__, __LINE__, transceiver_rsp.content.value); hwtimer_wait(5000); }