TSCH: latest update from https://github.com/EIT-ICT-RICH/contiki
This commit is contained in:
parent
27da5b8ab5
commit
7eabf8d391
@ -66,11 +66,11 @@
|
||||
#define ORCHESTRA_COMMON_SHARED_PERIOD 31
|
||||
#endif /* ORCHESTRA_CONF_COMMON_SHARED_PERIOD */
|
||||
|
||||
#ifdef ORCHESTRA_CONF_EBSF_PERIOD
|
||||
#define ORCHESTRA_UNICAST_PERIOD ORCHESTRA_CONF_EBSF_PERIOD
|
||||
#else /* ORCHESTRA_CONF_COMMON_SHARED_PERIOD */
|
||||
#ifdef ORCHESTRA_CONF_UNICAST_PERIOD
|
||||
#define ORCHESTRA_UNICAST_PERIOD ORCHESTRA_CONF_UNICAST_PERIOD
|
||||
#else /* ORCHESTRA_CONF_UNICAST_PERIOD */
|
||||
#define ORCHESTRA_UNICAST_PERIOD 17
|
||||
#endif /* ORCHESTRA_CONF_COMMON_SHARED_PERIOD */
|
||||
#endif /* ORCHESTRA_CONF_UNICAST_PERIOD */
|
||||
|
||||
/* Is the per-neighbor unicast slotframe sender-based (if not, it is receiver-based).
|
||||
* Note: sender-based works only with RPL storing mode as it relies on DAO and
|
||||
@ -81,12 +81,12 @@
|
||||
#define ORCHESTRA_UNICAST_SENDER_BASED 0
|
||||
#endif /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
|
||||
|
||||
/* The hash function used to assign timeslot to a diven node (based on its link-layer address) */
|
||||
/* The hash function used to assign timeslot to a given node (based on its link-layer address) */
|
||||
#ifdef ORCHESTRA_CONF_LINKADDR_HASH
|
||||
#define ORCHESTRA_LINKADDR_HASH ORCHESTRA_CONF_LINKADDR_HASH
|
||||
#else /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
|
||||
#else /* ORCHESTRA_CONF_LINKADDR_HASH */
|
||||
#define ORCHESTRA_LINKADDR_HASH(addr) ((addr != NULL) ? (addr)->u8[LINKADDR_SIZE - 1] : -1)
|
||||
#endif /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
|
||||
#endif /* ORCHESTRA_CONF_LINKADDR_HASH */
|
||||
|
||||
/* The maximum hash */
|
||||
#ifdef ORCHESTRA_CONF_MAX_HASH
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include "net/packetbuf.h"
|
||||
|
||||
#if ORCHESTRA_UNICAST_SENDER_BASED && ORCHESTRA_COLLISION_FREE_HASH
|
||||
#define UNICAST_SLOT_SHARED_FLAG ((ORCHESTRA_UNICAST_PERIOD < ORCHESTRA_MAX_HASH) ? LINK_OPTION_SHARED : 0)
|
||||
#define UNICAST_SLOT_SHARED_FLAG ((ORCHESTRA_UNICAST_PERIOD < (ORCHESTRA_MAX_HASH + 1)) ? LINK_OPTION_SHARED : 0)
|
||||
#else
|
||||
#define UNICAST_SLOT_SHARED_FLAG LINK_OPTION_SHARED
|
||||
#endif
|
||||
|
@ -43,7 +43,7 @@ four implementations it was tested against.
|
||||
|
||||
We have designed this implementation with IPv6 and RPL in mind, but the code is fully independent
|
||||
from upper layers (with the exception of the optional `tsch-rpl.[ch]`), and has been
|
||||
also tested with Rime (currently only with 64-bit link-later addresses).
|
||||
also tested with Rime (currently only with 64-bit link-layer addresses).
|
||||
|
||||
## Code structure
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "contiki.h"
|
||||
#include "lib/list.h"
|
||||
#include "lib/memb.h"
|
||||
#include "lib/random.h"
|
||||
#include "net/queuebuf.h"
|
||||
#include "net/mac/rdc.h"
|
||||
#include "net/mac/tsch/tsch.h"
|
||||
@ -76,24 +77,6 @@ LIST(neighbor_list);
|
||||
struct tsch_neighbor *n_broadcast;
|
||||
struct tsch_neighbor *n_eb;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* A pseudo-random generator with better properties than msp430-libc's default
|
||||
**/
|
||||
|
||||
static uint32_t tsch_random_seed;
|
||||
|
||||
static void
|
||||
tsch_random_init(uint32_t x)
|
||||
{
|
||||
tsch_random_seed = x;
|
||||
}
|
||||
static uint8_t
|
||||
tsch_random_byte(uint8_t window)
|
||||
{
|
||||
tsch_random_seed = tsch_random_seed * 1103515245 + 12345;
|
||||
return (tsch_random_seed / 65536) & window;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Add a TSCH neighbor */
|
||||
struct tsch_neighbor *
|
||||
@ -162,7 +145,15 @@ tsch_queue_update_time_source(const linkaddr_t *new_addr)
|
||||
if(!tsch_is_locked()) {
|
||||
if(!tsch_is_coordinator) {
|
||||
struct tsch_neighbor *old_time_src = tsch_queue_get_time_source();
|
||||
struct tsch_neighbor *new_time_src = new_addr ? tsch_queue_add_nbr(new_addr) : NULL;
|
||||
struct tsch_neighbor *new_time_src = NULL;
|
||||
|
||||
if(new_addr != NULL) {
|
||||
/* Get/add neighbor, return 0 in case of failure */
|
||||
new_time_src = tsch_queue_add_nbr(new_addr);
|
||||
if(new_time_src == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(new_time_src != old_time_src) {
|
||||
PRINTF("TSCH: update time source: %u -> %u\n",
|
||||
@ -181,9 +172,9 @@ tsch_queue_update_time_source(const linkaddr_t *new_addr)
|
||||
#ifdef TSCH_CALLBACK_NEW_TIME_SOURCE
|
||||
TSCH_CALLBACK_NEW_TIME_SOURCE(old_time_src, new_time_src);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -434,8 +425,10 @@ tsch_queue_backoff_inc(struct tsch_neighbor *n)
|
||||
{
|
||||
/* Increment exponent */
|
||||
n->backoff_exponent = MIN(n->backoff_exponent + 1, TSCH_MAC_MAX_BE);
|
||||
/* Pick a window (number of shared slots to skip) */
|
||||
n->backoff_window = tsch_random_byte((1 << n->backoff_exponent) - 1);
|
||||
/* Pick a window (number of shared slots to skip). Ignore least significant
|
||||
* few bits, which, on some embedded implementations of rand (e.g. msp430-libc),
|
||||
* are known to have poor pseudo-random properties. */
|
||||
n->backoff_window = (random_rand() >> 6) % (1 << n->backoff_exponent);
|
||||
/* Add one to the window as we will decrement it at the end of the current slot
|
||||
* through tsch_queue_update_all_backoff_windows */
|
||||
n->backoff_window++;
|
||||
@ -464,8 +457,6 @@ void
|
||||
tsch_queue_init(void)
|
||||
{
|
||||
list_init(neighbor_list);
|
||||
tsch_random_init(*((uint32_t *)&linkaddr_node_addr) +
|
||||
*((uint32_t *)&linkaddr_node_addr + 1));
|
||||
memb_init(&neighbor_memb);
|
||||
memb_init(&packet_memb);
|
||||
/* Add virtual EB and the broadcast neighbors */
|
||||
|
@ -49,15 +49,31 @@
|
||||
#ifdef TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR
|
||||
#define TSCH_QUEUE_NUM_PER_NEIGHBOR TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR
|
||||
#else
|
||||
/* By default, round QUEUEBUF_CONF_NUM to next power of two
|
||||
* (in the range [4;256]) */
|
||||
#if QUEUEBUF_CONF_NUM <= 4
|
||||
#define TSCH_QUEUE_NUM_PER_NEIGHBOR 4
|
||||
#elif QUEUEBUF_CONF_NUM <= 8
|
||||
#define TSCH_QUEUE_NUM_PER_NEIGHBOR 8
|
||||
#elif QUEUEBUF_CONF_NUM <= 16
|
||||
#define TSCH_QUEUE_NUM_PER_NEIGHBOR 16
|
||||
#elif QUEUEBUF_CONF_NUM <= 32
|
||||
#define TSCH_QUEUE_NUM_PER_NEIGHBOR 32
|
||||
#elif QUEUEBUF_CONF_NUM <= 64
|
||||
#define TSCH_QUEUE_NUM_PER_NEIGHBOR 64
|
||||
#elif QUEUEBUF_CONF_NUM <= 128
|
||||
#define TSCH_QUEUE_NUM_PER_NEIGHBOR 128
|
||||
#else
|
||||
#define TSCH_QUEUE_NUM_PER_NEIGHBOR 256
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* The number of neighbor queues. There two queues allocated for
|
||||
* one EBs, one for broadcasts. Other queues are real neighbors */
|
||||
/* The number of neighbor queues. There are two queues allocated at all times:
|
||||
* one for EBs, one for broadcasts. Other queues are for unicast to neighbors */
|
||||
#ifdef TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES
|
||||
#define TSCH_QUEUE_MAX_NEIGHBOR_QUEUES TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES
|
||||
#else
|
||||
#define TSCH_QUEUE_MAX_NEIGHBOR_QUEUES 8
|
||||
#define TSCH_QUEUE_MAX_NEIGHBOR_QUEUES ((NBR_TABLE_CONF_MAX_NEIGHBORS) + 2)
|
||||
#endif
|
||||
|
||||
/* TSCH CSMA-CA parameters, see IEEE 802.15.4e-2012 */
|
||||
|
@ -91,7 +91,7 @@
|
||||
#error TSCH_DEQUEUED_ARRAY_SIZE must be greater or equal to QUEUEBUF_NUM
|
||||
#endif
|
||||
#if (TSCH_DEQUEUED_ARRAY_SIZE & (TSCH_DEQUEUED_ARRAY_SIZE - 1)) != 0
|
||||
#error TSCH_QUEUE_NUM_PER_NEIGHBOR must be power of two
|
||||
#error TSCH_DEQUEUED_ARRAY_SIZE must be power of two
|
||||
#endif
|
||||
|
||||
/* Truncate received drift correction information to maximum half
|
||||
@ -190,7 +190,7 @@ tsch_get_lock(void)
|
||||
/* Issue a log whenever we had to busy wait until getting the lock */
|
||||
TSCH_LOG_ADD(tsch_log_message,
|
||||
snprintf(log->message, sizeof(log->message),
|
||||
"!get lock delay %u", busy_wait_time);
|
||||
"!get lock delay %u", (unsigned)busy_wait_time);
|
||||
);
|
||||
}
|
||||
return 1;
|
||||
@ -248,28 +248,24 @@ check_timer_miss(rtimer_clock_t ref_time, rtimer_clock_t offset, rtimer_clock_t
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Schedule a wakeup at a specified offset from a reference time.
|
||||
* Provides basic protection against missed deadlines and timer overflows
|
||||
* A non-zero return value signals to tsch_slot_operation a missed deadline.
|
||||
* If conditional: schedule only if the deadline is not missed, else busy wait.
|
||||
* If not conditional: schedule regardless of deadline miss. */
|
||||
* A return value of zero signals a missed deadline: no rtimer was scheduled. */
|
||||
static uint8_t
|
||||
tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_clock_t offset, int conditional, const char *str)
|
||||
tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_clock_t offset, const char *str)
|
||||
{
|
||||
rtimer_clock_t now = RTIMER_NOW();
|
||||
int r;
|
||||
/* Subtract RTIMER_GUARD before checking for deadline miss
|
||||
* because we can not schedule rtimer less than RTIMER_GUARD in the future */
|
||||
int missed = check_timer_miss(ref_time, offset - RTIMER_GUARD, now);
|
||||
|
||||
if(missed) {
|
||||
TSCH_LOG_ADD(tsch_log_message,
|
||||
snprintf(log->message, sizeof(log->message),
|
||||
"!dl-miss-%d %s %d %d",
|
||||
conditional, str,
|
||||
(int)(now-ref_time), (int)offset);
|
||||
"!dl-miss %s %d %d",
|
||||
str, (int)(now-ref_time), (int)offset);
|
||||
);
|
||||
|
||||
if(conditional) {
|
||||
BUSYWAIT_UNTIL_ABS(0, ref_time, offset);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
ref_time += offset;
|
||||
r = rtimer_set(tm, ref_time, 1, (void (*)(struct rtimer *, void *))tsch_slot_operation, NULL);
|
||||
@ -279,14 +275,16 @@ tsch_schedule_slot_operation(struct rtimer *tm, rtimer_clock_t ref_time, rtimer_
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Schedule slot operation conditionally, and YIELD if success only */
|
||||
/* Schedule slot operation conditionally, and YIELD if success only.
|
||||
* Always attempt to schedule RTIMER_GUARD before the target to make sure to wake up
|
||||
* ahead of time and then busy wait to exactly hit the target. */
|
||||
#define TSCH_SCHEDULE_AND_YIELD(pt, tm, ref_time, offset, str) \
|
||||
do { \
|
||||
if(tsch_schedule_slot_operation(tm, ref_time, offset, 1, str)) { \
|
||||
if(tsch_schedule_slot_operation(tm, ref_time, offset - RTIMER_GUARD, str)) { \
|
||||
PT_YIELD(pt); \
|
||||
} \
|
||||
BUSYWAIT_UNTIL_ABS(0, ref_time, offset); \
|
||||
} while(0);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Get EB, broadcast or unicast packet to be sent, and target neighbor. */
|
||||
static struct tsch_packet *
|
||||
@ -396,8 +394,6 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||
* successful Tx or Drop) */
|
||||
dequeued_index = ringbufindex_peek_put(&dequeued_ringbuf);
|
||||
if(dequeued_index != -1) {
|
||||
/* is this a data packet? */
|
||||
static uint8_t is_data;
|
||||
if(current_packet == NULL || current_packet->qb == NULL) {
|
||||
mac_tx_status = MAC_TX_ERR_FATAL;
|
||||
} else {
|
||||
@ -424,7 +420,6 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||
packet_len = queuebuf_datalen(current_packet->qb);
|
||||
/* is this a broadcast packet? (wait for ack?) */
|
||||
is_broadcast = current_neighbor->is_broadcast;
|
||||
is_data = ((((uint8_t *)(packet))[0]) & 7) == FRAME802154_DATAFRAME;
|
||||
/* read seqno from payload */
|
||||
seqno = ((uint8_t *)(packet))[2];
|
||||
/* if this is an EB, then update its Sync-IE */
|
||||
@ -601,7 +596,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||
log->tx.datalen = queuebuf_datalen(current_packet->qb);
|
||||
log->tx.drift = drift_correction;
|
||||
log->tx.drift_used = drift_neighbor != NULL;
|
||||
log->tx.is_data = is_data;
|
||||
log->tx.is_data = ((((uint8_t *)(queuebuf_dataptr(current_packet->qb)))[0]) & 7) == FRAME802154_DATAFRAME;
|
||||
log->tx.sec_level = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL);
|
||||
log->tx.dest = TSCH_LOG_ID_FROM_LINKADDR(queuebuf_addr(current_packet->qb, PACKETBUF_ADDR_RECEIVER));
|
||||
);
|
||||
@ -917,7 +912,7 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
||||
/* Update current slot start */
|
||||
prev_slot_start = current_slot_start;
|
||||
current_slot_start += time_to_next_active_slot;
|
||||
} while(!tsch_schedule_slot_operation(t, prev_slot_start, time_to_next_active_slot, 1, "main"));
|
||||
} while(!tsch_schedule_slot_operation(t, prev_slot_start, time_to_next_active_slot, "main"));
|
||||
}
|
||||
|
||||
tsch_in_slot_operation = 0;
|
||||
@ -952,7 +947,7 @@ tsch_slot_operation_start(void)
|
||||
/* Update current slot start */
|
||||
prev_slot_start = current_slot_start;
|
||||
current_slot_start += time_to_next_active_slot;
|
||||
} while(!tsch_schedule_slot_operation(&slot_operation_timer, prev_slot_start, time_to_next_active_slot, 1, "association"));
|
||||
} while(!tsch_schedule_slot_operation(&slot_operation_timer, prev_slot_start, time_to_next_active_slot, "association"));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Start actual slot operation */
|
||||
|
@ -47,7 +47,23 @@
|
||||
#ifdef TSCH_CONF_DEQUEUED_ARRAY_SIZE
|
||||
#define TSCH_DEQUEUED_ARRAY_SIZE TSCH_CONF_DEQUEUED_ARRAY_SIZE
|
||||
#else
|
||||
/* By default, round QUEUEBUF_CONF_NUM to next power of two
|
||||
* (in the range [4;256]) */
|
||||
#if QUEUEBUF_CONF_NUM <= 4
|
||||
#define TSCH_DEQUEUED_ARRAY_SIZE 4
|
||||
#elif QUEUEBUF_CONF_NUM <= 8
|
||||
#define TSCH_DEQUEUED_ARRAY_SIZE 8
|
||||
#elif QUEUEBUF_CONF_NUM <= 16
|
||||
#define TSCH_DEQUEUED_ARRAY_SIZE 16
|
||||
#elif QUEUEBUF_CONF_NUM <= 32
|
||||
#define TSCH_DEQUEUED_ARRAY_SIZE 32
|
||||
#elif QUEUEBUF_CONF_NUM <= 64
|
||||
#define TSCH_DEQUEUED_ARRAY_SIZE 64
|
||||
#elif QUEUEBUF_CONF_NUM <= 128
|
||||
#define TSCH_DEQUEUED_ARRAY_SIZE 128
|
||||
#else
|
||||
#define TSCH_DEQUEUED_ARRAY_SIZE 256
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Size of the ring buffer storing incoming packets.
|
||||
|
@ -391,7 +391,7 @@ tsch_tx_process_pending()
|
||||
ringbufindex_get(&dequeued_ringbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Setup TSCH as a coordinator */
|
||||
static void
|
||||
tsch_start_coordinator(void)
|
||||
@ -407,15 +407,13 @@ tsch_start_coordinator(void)
|
||||
tsch_is_associated = 1;
|
||||
tsch_join_priority = 0;
|
||||
|
||||
PRINTF("TSCH: starting as coordinator, asn-%x.%lx\n",
|
||||
current_asn.ms1b, current_asn.ls4b);
|
||||
PRINTF("TSCH: starting as coordinator, PAN ID %x, asn-%x.%lx\n",
|
||||
frame802154_get_pan_id(), current_asn.ms1b, current_asn.ls4b);
|
||||
|
||||
/* Start only after some initial delay */
|
||||
tsch_slot_operation_sync(
|
||||
RTIMER_NOW() + TSCH_CLOCK_TO_TICKS(CLOCK_SECOND / 10),
|
||||
¤t_asn);
|
||||
/* Start slot operation */
|
||||
tsch_slot_operation_sync(RTIMER_NOW(), ¤t_asn);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Leave the TSCH network */
|
||||
void
|
||||
tsch_disassociate(void)
|
||||
@ -426,7 +424,7 @@ tsch_disassociate(void)
|
||||
PRINTF("TSCH: leaving the network\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Attempt to associate to a network form an incoming EB */
|
||||
static int
|
||||
tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
|
||||
|
@ -133,11 +133,7 @@
|
||||
#undef UIP_CONF_TCP
|
||||
#define UIP_CONF_TCP 0
|
||||
#undef QUEUEBUF_CONF_NUM
|
||||
#define QUEUEBUF_CONF_NUM 6
|
||||
#undef TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR
|
||||
#define TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR 8
|
||||
#undef TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES
|
||||
#define TSCH_QUEUE_CONF_MAX_NEIGHBOR_QUEUES 6
|
||||
#define QUEUEBUF_CONF_NUM 4
|
||||
#undef UIP_CONF_MAX_ROUTES
|
||||
#define UIP_CONF_MAX_ROUTES 8
|
||||
#undef NBR_TABLE_CONF_MAX_NEIGHBORS
|
||||
|
Loading…
Reference in New Issue
Block a user