mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2026-01-01 01:41:18 +01:00
Merge branch 'rpl' of ssh://ukleos.org:2222/home/git/ukleos
Conflicts: board/msba2-common/tools/src/control_2xxx.c drivers/cc110x/cc1100-interface.h projects/test_rpl/main.c sys/include/vtimer.h sys/net/sixlowpan/rpl/Jamfile sys/net/sixlowpan/rpl/objective_functions.c sys/net/sixlowpan/rpl/objective_functions.h sys/net/sixlowpan/rpl/of0.c sys/net/sixlowpan/rpl/of0.h sys/net/sixlowpan/rpl/rpl.c sys/net/sixlowpan/rpl/rpl_dodag.c sys/net/sixlowpan/rpl/rpl_structs.h sys/net/sixlowpan/rpl/trickle.c sys/net/sixlowpan/sixlowmac.c sys/vtimer/vtimer.c
This commit is contained in:
commit
bf85e4902c
@ -66,6 +66,9 @@ 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
|
||||
#ifdef MODULE_RPL
|
||||
#warning RPL currently works with CC1100_MODE_WOR
|
||||
#endif
|
||||
#define CC1100_RADIO_MODE CC1100_MODE_CONSTANT_RX
|
||||
#endif
|
||||
|
||||
|
||||
@ -96,4 +96,14 @@ int vtimer_remove(vtimer_t *t);
|
||||
*/
|
||||
void vtimer_print(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 */
|
||||
|
||||
506
sys/net/sixlowpan/rpl/etx_beaconing.c
Normal file
506
sys/net/sixlowpan/rpl/etx_beaconing.c
Normal file
@ -0,0 +1,506 @@
|
||||
/*
|
||||
* etx_beaconing.c
|
||||
*
|
||||
* Created on: Feb 26, 2013
|
||||
* Author: stephan
|
||||
*/
|
||||
#include "etx_beaconing.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <hwtimer.h>
|
||||
#include <vtimer.h>
|
||||
#include <thread.h>
|
||||
#include <transceiver.h>
|
||||
|
||||
#include "sys/net/sixlowpan/sixlowmac.h"
|
||||
#include "sys/net/sixlowpan/ieee802154_frame.h"
|
||||
|
||||
//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 };
|
||||
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 };
|
||||
|
||||
//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 };
|
||||
|
||||
/*
|
||||
* 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 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
|
||||
* 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 ETX_MAX_CANDIDATE_NEIHGBORS
|
||||
* 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
|
||||
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
|
||||
* 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;
|
||||
|
||||
//Message to send probes with
|
||||
msg_t mesg;
|
||||
|
||||
//RPL-address
|
||||
static ipv6_addr_t * own_address;
|
||||
|
||||
static etx_probe_t * etx_get_send_buf(void) {
|
||||
return ((etx_probe_t *) &(etx_send_buf[0]));
|
||||
}
|
||||
static etx_probe_t * etx_get_rec_buf(void) {
|
||||
return ((etx_probe_t *) &(etx_rec_buf[0]));
|
||||
}
|
||||
|
||||
void show_candidates(void) {
|
||||
etx_neighbor_t * candidate;
|
||||
etx_neighbor_t *end;
|
||||
|
||||
for (candidate = &candidates[0], end = candidates
|
||||
+ ETX_MAX_CANDIDATE_NEIGHBORS; candidate < end;
|
||||
candidate++) {
|
||||
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_PKT_OPTVAL;
|
||||
|
||||
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");
|
||||
|
||||
etx_clock_pid = thread_create(etx_clock_buf, ETX_CLOCK_STACKSIZE,
|
||||
PRIORITY_MAIN - 1, CREATE_STACKTEST,
|
||||
etx_clock, "etx_clock");
|
||||
//register at transceiver
|
||||
transceiver_register(TRANSCEIVER_CC1100, etx_radio_pid);
|
||||
puts("...[DONE]");
|
||||
}
|
||||
|
||||
void etx_beacon(void) {
|
||||
/*
|
||||
* 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 * packet = etx_get_send_buf();
|
||||
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) {
|
||||
thread_sleep();
|
||||
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");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 < ETX_MAX_CANDIDATE_NEIGHBORS; i++) {
|
||||
if (candidates[i].used
|
||||
&& (etx_equal_id(&candidates[i].addr, address))) {
|
||||
return &candidates[i];
|
||||
}
|
||||
}
|
||||
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) {
|
||||
etx_neighbor_t * candidate = etx_find_candidate(address);
|
||||
if (candidate != NULL ) {
|
||||
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;
|
||||
}
|
||||
|
||||
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.
|
||||
* 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 the pointer to the candidate if it was added, or a NULL-pointer
|
||||
* otherwise.
|
||||
*/
|
||||
etx_neighbor_t * candidate;
|
||||
etx_neighbor_t * end;
|
||||
|
||||
for (candidate = &candidates[0], end = candidates
|
||||
+ ETX_MAX_CANDIDATE_NEIGHBORS; candidate < end;
|
||||
candidate++) {
|
||||
if (candidate->used) {
|
||||
//skip
|
||||
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_rx = 0;
|
||||
candidate->used = 1;
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
DEBUG(
|
||||
"ETX beacon package received with following values:\n"
|
||||
"\tPackage Option:%x\n"
|
||||
"\t Data Length:%u\n"
|
||||
"\tSource Address:%d\n\n", etx_rec_buf[ETX_PKT_OPT], etx_rec_buf[ETX_PKT_LEN],
|
||||
candidate_address->uint8[ETX_IPV6_LAST_BYTE]);
|
||||
|
||||
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);
|
||||
if (candidate == NULL ) {
|
||||
puts("[ERROR] Candidate could not get added");
|
||||
puts("Increase the constant ETX_MAX_CANDIDATE_NEIHGBORS");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//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.
|
||||
etx_probe_t * rec_pkt = etx_get_rec_buf();
|
||||
|
||||
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_pkt->data[i * ETX_TUPLE_SIZE],
|
||||
rec_pkt->data[i * ETX_TUPLE_SIZE + ETX_PKT_REC_OFFSET]);
|
||||
|
||||
if (rec_pkt->data[i * ETX_TUPLE_SIZE]
|
||||
== own_address->uint8[ETX_IPV6_LAST_BYTE]) {
|
||||
|
||||
candidate->packets_rx = rec_pkt->data[i * ETX_TUPLE_SIZE
|
||||
+ ETX_PKT_REC_OFFSET];
|
||||
}
|
||||
}
|
||||
|
||||
//Last, update the ETX value for this candidate
|
||||
etx_update(candidate);
|
||||
}
|
||||
|
||||
void etx_radio(void) {
|
||||
msg_t m;
|
||||
radio_packet_t *p;
|
||||
|
||||
ieee802154_frame_t frame;
|
||||
|
||||
msg_init_queue(msg_que, ETX_RCV_QUEUE_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) {
|
||||
msg_receive(&m);
|
||||
if (m.type == PKT_PENDING) {
|
||||
p = (radio_packet_t*) m.content.ptr;
|
||||
|
||||
read_802154_frame(p->data, &frame, p->length);
|
||||
|
||||
if (frame.payload[0] == ETX_PKT_OPTVAL) {
|
||||
//copy to receive buffer
|
||||
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[ETX_IPV6_LAST_BYTE] = (uint8_t) p->src;
|
||||
//handle the beacon
|
||||
mutex_lock(&etx_mutex);
|
||||
etx_handle_beacon(&candidate_addr);
|
||||
mutex_unlock(&etx_mutex,1);
|
||||
}
|
||||
|
||||
p->processing--;
|
||||
}
|
||||
else if (m.type == ENOBUFFER) {
|
||||
puts("Transceiver buffer full");
|
||||
}
|
||||
else {
|
||||
//packet is not for me, whatever
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void etx_update(etx_neighbor_t * candidate) {
|
||||
DEBUG("update!\n");
|
||||
/*
|
||||
* Update the current ETX value of a candidate
|
||||
*/
|
||||
double d_f;
|
||||
double d_r;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate d_f (the forward PDR) from ME to this candidate.
|
||||
*/
|
||||
d_f = candidate->packets_rx / (double) ETX_WINDOW;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
DEBUG("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
|
||||
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 {
|
||||
//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 < ETX_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
119
sys/net/sixlowpan/rpl/etx_beaconing.h
Normal file
119
sys/net/sixlowpan/rpl/etx_beaconing.h
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Header for the ETX-beaconing module
|
||||
* etx_beaconing.h
|
||||
*
|
||||
* Created on: Feb 26, 2013
|
||||
* Author: stephan
|
||||
*/
|
||||
|
||||
#ifndef ETX_BEACONING_H_
|
||||
#define ETX_BEACONING_H_
|
||||
|
||||
#include "sys/net/sixlowpan/sixlowip.h"
|
||||
|
||||
//For debugging purposes
|
||||
#define ENABLE_DEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#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
|
||||
#define ETX_BUF_SIZE (32)
|
||||
|
||||
#define ETX_RCV_QUEUE_SIZE (128)
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
/*
|
||||
* 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_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
|
||||
#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)
|
||||
#define ETX_CLOCK_ADJUST (52500) //Adjustment for clockthread computations to stay close/near ETX_INTERVAL
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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[30];
|
||||
} 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[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
|
||||
} 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_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
|
||||
|
||||
#endif /* ETX_BEACONING_H_ */
|
||||
@ -1,7 +0,0 @@
|
||||
#include "objective_functions.h"
|
||||
|
||||
void of0(void)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void of0(void);
|
||||
@ -18,6 +18,12 @@
|
||||
#include <string.h>
|
||||
#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,
|
||||
@ -73,6 +79,7 @@ rpl_parent_t *which_parent(rpl_parent_t *p1, rpl_parent_t *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)
|
||||
{
|
||||
return d1;
|
||||
|
||||
@ -1,8 +1,3 @@
|
||||
#include "rpl_structs.h"
|
||||
|
||||
rpl_of_t *rpl_get_of0(void);
|
||||
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 *);
|
||||
|
||||
|
||||
160
sys/net/sixlowpan/rpl/of_mrhof.c
Normal file
160
sys/net/sixlowpan/rpl/of_mrhof.c
Normal file
@ -0,0 +1,160 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#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 *);
|
||||
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;
|
||||
rpl_parent_t * cur_preferred_parent = NULL;
|
||||
|
||||
rpl_of_t rpl_of_mrhof = {
|
||||
0x1,
|
||||
calc_rank,
|
||||
which_parent,
|
||||
which_dodag,
|
||||
reset,
|
||||
NULL
|
||||
};
|
||||
|
||||
rpl_of_t * rpl_get_of_mrhof(void) {
|
||||
return &rpl_of_mrhof;
|
||||
}
|
||||
|
||||
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.
|
||||
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
|
||||
*
|
||||
* 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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t calc_rank(rpl_parent_t * parent, uint16_t base_rank) {
|
||||
puts("calc_rank");
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
if (parent == NULL ) {
|
||||
if (base_rank == 0) {
|
||||
//No parent, no rank, a root node would have a rank != 0
|
||||
return INFINITE_RANK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
* desirable.
|
||||
*
|
||||
*/
|
||||
uint16_t path_p1 = calc_path_cost(p1);
|
||||
uint16_t path_p2 = calc_path_cost(p2);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
static rpl_dodag_t * which_dodag(rpl_dodag_t *d1, rpl_dodag_t *d2) {
|
||||
return d1;
|
||||
}
|
||||
40
sys/net/sixlowpan/rpl/of_mrhof.h
Normal file
40
sys/net/sixlowpan/rpl/of_mrhof.h
Normal file
@ -0,0 +1,40 @@
|
||||
//For debugging purposes
|
||||
#define ENABLE_DEBUG
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
#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 (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)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#define ETX_RANK_MULTIPLIER (0x80)
|
||||
|
||||
rpl_of_t *rpl_get_of_mrhof();
|
||||
@ -21,7 +21,9 @@
|
||||
#include <mutex.h>
|
||||
#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"
|
||||
@ -210,8 +212,13 @@ 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);
|
||||
|
||||
return SUCCESS;
|
||||
/* Initialize ETX-calculation if needed */
|
||||
if(RPL_DEFAULT_OCP == 1){
|
||||
puts("INIT ETX BEACONING");
|
||||
etx_init_beaconing(&my_address);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void rpl_init_root(void)
|
||||
@ -246,6 +253,7 @@ void rpl_init_root(void)
|
||||
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 = RPL_ROOT_RANK;
|
||||
dodag->joined = 1;
|
||||
dodag->my_preferred_parent = NULL;
|
||||
@ -453,8 +461,6 @@ void send_DAO_ACK(ipv6_addr_t *destination)
|
||||
uint16_t plen = ICMPV6_HDR_LEN + DIS_BASE_LEN;
|
||||
rpl_send(destination, (uint8_t *)icmp_send_buf, plen, PROTO_NUM_ICMPV6, NULL);
|
||||
mutex_unlock(&rpl_send_mutex, 0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void rpl_process(void)
|
||||
@ -498,7 +504,6 @@ void rpl_process(void)
|
||||
|
||||
default:
|
||||
mutex_unlock(&rpl_recv_mutex, 0);
|
||||
puts("default unlock");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -847,7 +852,6 @@ void recv_rpl_dao(void)
|
||||
len += rpl_opt_transit_buf->length + 2;
|
||||
/* Die eigentliche Lebenszeit einer Route errechnet sich aus (Lifetime aus DAO) * (Lifetime Unit) Sekunden */
|
||||
rpl_add_routing_entry(&rpl_opt_target_buf->target, &ipv6_buf->srcaddr, rpl_opt_transit_buf->path_lifetime * my_dodag->lifetime_unit);
|
||||
/* puts("Updated route \n"); */
|
||||
increment_seq = 1;
|
||||
break;
|
||||
}
|
||||
@ -898,6 +902,7 @@ void recv_rpl_dao_ack(void)
|
||||
|
||||
}
|
||||
|
||||
/* TODO: 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;
|
||||
|
||||
@ -23,6 +23,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
|
||||
|
||||
|
||||
@ -317,6 +317,7 @@ 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->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;
|
||||
|
||||
@ -70,6 +70,14 @@
|
||||
#define RPL_COUNTER_GREATER_THAN_LOCAL(A,B) (((A<B) && (RPL_COUNTER_LOWER_REGION + 1 - B + A < RPL_COUNTER_SEQ_WINDOW)) || ((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
|
||||
@ -77,7 +85,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
|
||||
@ -89,6 +96,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
|
||||
@ -98,7 +106,7 @@
|
||||
|
||||
/* others */
|
||||
|
||||
#define NUMBER_IMPLEMENTED_OFS 1
|
||||
#define NUMBER_IMPLEMENTED_OFS 2
|
||||
#define RPL_MAX_DODAGS 3
|
||||
#define RPL_MAX_INSTANCES 1
|
||||
#define RPL_MAX_PARENTS 5
|
||||
@ -114,8 +122,9 @@
|
||||
#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 {
|
||||
uint8_t rpl_instanceid;
|
||||
uint8_t version_number;
|
||||
@ -132,6 +141,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;
|
||||
@ -139,6 +149,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;
|
||||
@ -146,16 +157,19 @@ struct __attribute__((packed)) rpl_dao_ack_t {
|
||||
uint8_t status;
|
||||
};
|
||||
|
||||
/* DODAG ID Struct */
|
||||
/* 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)) {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
} rpl_opt_t;
|
||||
|
||||
/* DODAG Configuration-Option (RFC 6550 Fig. 24) */
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
@ -171,6 +185,7 @@ typedef struct __attribute__((packed)) {
|
||||
uint16_t lifetime_unit;
|
||||
} rpl_opt_dodag_conf_t;
|
||||
|
||||
/* RPL Solicited Information Option (RFC 6550 Fig. 28) */
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
@ -180,7 +195,8 @@ typedef struct __attribute__((packed)) {
|
||||
uint8_t version;
|
||||
} rpl_opt_solicited_t;
|
||||
|
||||
/* ipv6_addr_t target may be replaced by a target prefix of variable length */
|
||||
/* RPL Target-Option (RFC 6550 Fig. 25) */
|
||||
/* TODO: ipv6_addr_t target may be replaced by a target prefix of variable length */
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
@ -189,6 +205,7 @@ typedef struct __attribute__((packed)) {
|
||||
ipv6_addr_t target;
|
||||
} rpl_opt_target_t;
|
||||
|
||||
/* RPL Transit-Option (RFC 6550 Fig. 26) */
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
@ -201,12 +218,14 @@ typedef struct __attribute__((packed)) {
|
||||
struct rpl_dodag_t;
|
||||
|
||||
typedef struct {
|
||||
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;
|
||||
@ -218,6 +237,7 @@ typedef struct {
|
||||
|
||||
} 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;
|
||||
@ -235,6 +255,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;
|
||||
@ -244,11 +265,13 @@ typedef struct 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 * 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)(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 {
|
||||
|
||||
@ -24,9 +24,10 @@
|
||||
#include "trickle.h"
|
||||
#include "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;
|
||||
@ -70,6 +71,22 @@ void reset_trickletimer(void)
|
||||
|
||||
void init_trickle(void)
|
||||
{
|
||||
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 = 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 = calloc(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,
|
||||
@ -85,7 +102,6 @@ void init_trickle(void)
|
||||
rt_timer_over_pid = thread_create(routing_table_buf, RT_STACKSIZE,
|
||||
PRIORITY_MAIN - 1, CREATE_STACKTEST,
|
||||
rt_timer_over, "rt_timer_over");
|
||||
|
||||
}
|
||||
|
||||
void start_trickle(uint8_t DIOIntMin, uint8_t DIOIntDoubl,
|
||||
|
||||
@ -225,7 +225,6 @@ 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: %"PRIu32"\n", __FILE__, __LINE__, transceiver_rsp.content.value);
|
||||
|
||||
hwtimer_wait(5000);
|
||||
}
|
||||
|
||||
@ -129,9 +129,12 @@ void vtimer_callback(void *ptr)
|
||||
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 {
|
||||
DEBUG("Timer was poisoned.");
|
||||
}
|
||||
|
||||
in_callback = false;
|
||||
update_shortterm();
|
||||
@ -285,7 +288,15 @@ int vtimer_set_msg(vtimer_t *t, timex_t interval, unsigned int pid, void *ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vtimer_print(vtimer_t *t)
|
||||
void vtimer_print_short_queue(){
|
||||
queue_print(&shortterm_queue_root);
|
||||
}
|
||||
|
||||
void vtimer_print_long_queue(){
|
||||
queue_print(&longterm_queue_root);
|
||||
}
|
||||
|
||||
static void vtimer_print(vtimer_t *t)
|
||||
{
|
||||
printf("Seconds: %"PRIu32" - Microseconds: %"PRIu32"\n \
|
||||
action: %p\n \
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user