Merge branch 'contiki'

Conflicts:
	cpu/cc26xx-cc13xx/lib/cc13xxware
	cpu/cc26xx-cc13xx/lib/cc26xxware
This commit is contained in:
Harald Pichler 2017-01-31 15:00:59 +01:00
commit 2f8549aaae
319 changed files with 58114 additions and 6745 deletions

View file

@ -207,13 +207,13 @@ static int we_are_receiving_burst = 0;
#define INTER_PACKET_INTERVAL RTIMER_ARCH_SECOND / 2500
#endif
/* AFTER_ACK_DETECTECT_WAIT_TIME is the time to wait after a potential
/* AFTER_ACK_DETECTED_WAIT_TIME is the time to wait after a potential
ACK packet has been detected until we can read it out from the
radio. */
#ifdef CONTIKIMAC_CONF_AFTER_ACK_DETECTECT_WAIT_TIME
#define AFTER_ACK_DETECTECT_WAIT_TIME CONTIKIMAC_CONF_AFTER_ACK_DETECTECT_WAIT_TIME
#ifdef CONTIKIMAC_CONF_AFTER_ACK_DETECTED_WAIT_TIME
#define AFTER_ACK_DETECTED_WAIT_TIME CONTIKIMAC_CONF_AFTER_ACK_DETECTED_WAIT_TIME
#else
#define AFTER_ACK_DETECTECT_WAIT_TIME RTIMER_ARCH_SECOND / 1500
#define AFTER_ACK_DETECTED_WAIT_TIME RTIMER_ARCH_SECOND / 1500
#endif
/* MAX_PHASE_STROBE_TIME is the time that we transmit repeated packets
@ -766,7 +766,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
NETSTACK_RADIO.channel_clear() == 0)) {
uint8_t ackbuf[ACK_LEN];
wt = RTIMER_NOW();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTECT_WAIT_TIME)) { }
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + AFTER_ACK_DETECTED_WAIT_TIME)) { }
len = NETSTACK_RADIO.read(ackbuf, ACK_LEN);
if(len == ACK_LEN && seqno == ackbuf[ACK_LEN - 1]) {
@ -878,6 +878,10 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
if(next != NULL) {
packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1);
}
#if !NETSTACK_CONF_BRIDGE_MODE
/* If NETSTACK_CONF_BRIDGE_MODE is set, assume PACKETBUF_ADDR_SENDER is already set. */
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#endif
packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
if(NETSTACK_FRAMER.create() < 0) {
PRINTF("contikimac: framer failed\n");

View file

@ -231,10 +231,12 @@ tx_done(int status, struct rdc_buf_list *q, struct neighbor_queue *n)
mac_callback_t sent;
struct qbuf_metadata *metadata;
void *cptr;
uint8_t ntx;
metadata = (struct qbuf_metadata *)q->ptr;
sent = metadata->sent;
cptr = metadata->cptr;
ntx = n->transmissions;
switch(status) {
case MAC_TX_OK:
@ -251,7 +253,7 @@ tx_done(int status, struct rdc_buf_list *q, struct neighbor_queue *n)
}
free_packet(n, q, status);
mac_call_sent_callback(sent, cptr, status, n->transmissions);
mac_call_sent_callback(sent, cptr, status, ntx);
}
/*---------------------------------------------------------------------------*/
static void

View file

@ -146,24 +146,45 @@ frame802154_has_panid(frame802154_fcf_t *fcf, int *has_src_pan_id, int *has_dest
}
if(fcf->frame_version == FRAME802154_IEEE802154E_2012) {
/* IEEE 802.15.4e-2012, Table 2a, PAN ID Compression */
if(!fcf->panid_compression) {
if(fcf->dest_addr_mode) {
/* Use destination PAN ID if destination address is present */
dest_pan_id = 1;
} else if(fcf->src_addr_mode) {
/* Only src address, include src PAN ID */
src_pan_id = 1;
}
} else if((fcf->dest_addr_mode == 0) && (fcf->src_addr_mode == 0)) {
/* No address included: PAN ID compression flag changes meaning */
/*
* IEEE 802.15.4-2015
* Table 7-2, PAN ID Compression value for frame version 0b10
*/
if((fcf->dest_addr_mode == FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_NOADDR &&
fcf->panid_compression == 1) ||
(fcf->dest_addr_mode != FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_NOADDR &&
fcf->panid_compression == 0) ||
(fcf->dest_addr_mode == FRAME802154_LONGADDRMODE &&
fcf->src_addr_mode == FRAME802154_LONGADDRMODE &&
fcf->panid_compression == 0) ||
((fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
fcf->src_addr_mode != FRAME802154_NOADDR) ||
(fcf->dest_addr_mode != FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE)) ){
dest_pan_id = 1;
}
if(fcf->panid_compression == 0 &&
((fcf->dest_addr_mode == FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_LONGADDRMODE) ||
(fcf->dest_addr_mode == FRAME802154_NOADDR &&
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE) ||
(fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE) ||
(fcf->dest_addr_mode == FRAME802154_SHORTADDRMODE &&
fcf->src_addr_mode == FRAME802154_LONGADDRMODE) ||
(fcf->dest_addr_mode == FRAME802154_LONGADDRMODE &&
fcf->src_addr_mode == FRAME802154_SHORTADDRMODE))) {
src_pan_id = 1;
}
} else {
/* No PAN ID in ACK */
if(fcf->frame_type != FRAME802154_ACKFRAME) {
if(!fcf->panid_compression && fcf->src_addr_mode & 3) {
/* If compressed, don't inclue source PAN ID */
/* If compressed, don't include source PAN ID */
src_pan_id = 1;
}
if(fcf->dest_addr_mode & 3) {

View file

@ -70,7 +70,7 @@ struct ieee802154_ies {
uint16_t ie_mlme_len;
/* Payload Short MLME IEs */
uint8_t ie_tsch_synchronization_offset;
struct asn_t ie_asn;
struct tsch_asn_t ie_asn;
uint8_t ie_join_priority;
uint8_t ie_tsch_timeslot_id;
uint16_t ie_tsch_timeslot[tsch_ts_elements_count];

View file

@ -173,7 +173,8 @@ create_frame(int type, int do_create)
* Set up the source address using only the long address mode for
* phase 1.
*/
linkaddr_copy((linkaddr_t *)&params.src_addr, &linkaddr_node_addr);
linkaddr_copy((linkaddr_t *)&params.src_addr,
packetbuf_addr(PACKETBUF_ADDR_SENDER));
params.payload = packetbuf_dataptr();
params.payload_len = packetbuf_datalen();

View file

@ -46,10 +46,10 @@
#include "net/rime/rimestats.h"
#include <string.h>
#if CONTIKI_TARGET_COOJA
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA */
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
#define DEBUG 0
#if DEBUG
@ -158,10 +158,10 @@ send_one_packet(mac_callback_t sent, void *ptr)
wt = RTIMER_NOW();
watchdog_periodic();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + ACK_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
simProcessRunValue = 1;
cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
}
ret = MAC_TX_NOACK;
@ -176,10 +176,10 @@ send_one_packet(mac_callback_t sent, void *ptr)
watchdog_periodic();
while(RTIMER_CLOCK_LT(RTIMER_NOW(),
wt + AFTER_ACK_DETECTED_WAIT_TIME)) {
#if CONTIKI_TARGET_COOJA
simProcessRunValue = 1;
cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA */
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
simProcessRunValue = 1;
cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
}
}
@ -195,8 +195,8 @@ send_one_packet(mac_callback_t sent, void *ptr)
}
}
} else {
PRINTF("nullrdc tx noack\n");
}
PRINTF("nullrdc tx noack\n");
}
}
break;
case RADIO_TX_COLLISION:
@ -303,7 +303,7 @@ packet_input(void)
}
#endif /* RDC_WITH_DUPLICATE_DETECTION */
#endif /* NULLRDC_802154_AUTOACK */
#if NULLRDC_SEND_802154_ACK
{
frame802154_t info154;

View file

@ -42,6 +42,7 @@ It has been tested on the following platforms:
* Zolertia Zoul (`zoul`, tested on hardware)
* OpenMote-CC2538 (`openmote-cc2538`, tested on hardware)
* CC2650 (`srf06-cc26xx`, tested on hardware)
* Cooja mote (`cooja`, tested with cooja)
This implementation was present at the ETSI Plugtest
event in Prague in July 2015, and did successfully inter-operate with all
@ -83,7 +84,7 @@ Orchestra is implemented in:
A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`.
To use TSCH, first make sure your platform supports it.
Currently, `jn516x`, `sky`, `z1`, `cc2538dk`, `zoul`, `openmote-cc2538`, and `srf06-cc26xx` are the supported platforms.
Currently, `jn516x`, `sky`, `z1`, `cc2538dk`, `zoul`, `openmote-cc2538`, `srf06-cc26xx`, and `cooja` are the supported platforms.
To add your own, we refer the reader to the next section.
To add TSCH to your application, first include the TSCH module from your makefile with:
@ -179,7 +180,7 @@ Instead, TSCH will poll the driver for incoming packets, from interrupt, exactly
TSCH will check when initializing (in `tsch_init`) that the radio driver supports all required features, namely:
* get and set Rx mode (`RADIO_PARAM_RX_MODE`) as follows:
* enable address filtering with `RADIO_RX_MODE_ADDRESS_FILTER`
* disable address filtering with `RADIO_RX_MODE_ADDRESS_FILTER`
* disable auto-ack with `RADIO_RX_MODE_AUTOACK`
* enable poll mode with `RADIO_RX_MODE_POLL_MODE`
* get and set Tx mode (`RADIO_PARAM_TX_MODE`) as follows:

View file

@ -38,8 +38,10 @@
*
*/
#include "tsch-adaptive-timesync.h"
#include "tsch-log.h"
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/tsch-conf.h"
#include "net/mac/tsch/tsch-adaptive-timesync.h"
#include "net/mac/tsch/tsch-log.h"
#include <stdio.h>
#if TSCH_ADAPTIVE_TIMESYNC
@ -72,6 +74,10 @@ timesync_entry_add(int32_t val, uint32_t time_delta)
buffer[pos] = val;
if(timesync_entry_count < NUM_TIMESYNC_ENTRIES) {
timesync_entry_count++;
} else {
/* We now have accurate drift compensation.
* Increase keep-alive timeout. */
tsch_set_ka_timeout(TSCH_MAX_KEEPALIVE_TIMEOUT);
}
pos = (pos + 1) % NUM_TIMESYNC_ENTRIES;

View file

@ -44,13 +44,13 @@
/************ Types ***********/
/* The ASN is an absolute slot number over 5 bytes. */
struct asn_t {
struct tsch_asn_t {
uint32_t ls4b; /* least significant 4 bytes */
uint8_t ms1b; /* most significant 1 byte */
};
/* For quick modulo operation on ASN */
struct asn_divisor_t {
struct tsch_asn_divisor_t {
uint16_t val; /* Divisor value */
uint16_t asn_ms1b_remainder; /* Remainder of the operation 0x100000000 / val */
};
@ -58,38 +58,38 @@ struct asn_divisor_t {
/************ Macros **********/
/* Initialize ASN */
#define ASN_INIT(asn, ms1b_, ls4b_) do { \
#define TSCH_ASN_INIT(asn, ms1b_, ls4b_) do { \
(asn).ms1b = (ms1b_); \
(asn).ls4b = (ls4b_); \
} while(0);
/* Increment an ASN by inc (32 bits) */
#define ASN_INC(asn, inc) do { \
#define TSCH_ASN_INC(asn, inc) do { \
uint32_t new_ls4b = (asn).ls4b + (inc); \
if(new_ls4b < (asn).ls4b) { (asn).ms1b++; } \
(asn).ls4b = new_ls4b; \
} while(0);
/* Decrement an ASN by inc (32 bits) */
#define ASN_DEC(asn, dec) do { \
#define TSCH_ASN_DEC(asn, dec) do { \
uint32_t new_ls4b = (asn).ls4b - (dec); \
if(new_ls4b > (asn).ls4b) { (asn).ms1b--; } \
(asn).ls4b = new_ls4b; \
} while(0);
/* Returns the 32-bit diff between asn1 and asn2 */
#define ASN_DIFF(asn1, asn2) \
#define TSCH_ASN_DIFF(asn1, asn2) \
((asn1).ls4b - (asn2).ls4b)
/* Initialize a struct asn_divisor_t */
#define ASN_DIVISOR_INIT(div, val_) do { \
#define TSCH_ASN_DIVISOR_INIT(div, val_) do { \
(div).val = (val_); \
(div).asn_ms1b_remainder = ((0xffffffff % (val_)) + 1) % (val_); \
} while(0);
/* Returns the result (16 bits) of a modulo operation on ASN,
* with divisor being a struct asn_divisor_t */
#define ASN_MOD(asn, div) \
#define TSCH_ASN_MOD(asn, div) \
((uint16_t)((asn).ls4b % (div).val) \
+ (uint16_t)((asn).ms1b * (div).asn_ms1b_remainder % (div).val)) \
% (div).val

View file

@ -174,7 +174,7 @@
#ifdef TSCH_CONF_ADAPTIVE_TIMESYNC
#define TSCH_ADAPTIVE_TIMESYNC TSCH_CONF_ADAPTIVE_TIMESYNC
#else
#define TSCH_ADAPTIVE_TIMESYNC 0
#define TSCH_ADAPTIVE_TIMESYNC 1
#endif
/* HW frame filtering enabled */

View file

@ -132,7 +132,7 @@ tsch_log_prepare_add(void)
int log_index = ringbufindex_peek_put(&log_ringbuf);
if(log_index != -1) {
struct tsch_log_t *log = &log_array[log_index];
log->asn = current_asn;
log->asn = tsch_current_asn;
log->link = current_link;
return log;
} else {

View file

@ -81,7 +81,7 @@ struct tsch_log_t {
tsch_log_rx,
tsch_log_message
} type;
struct asn_t asn;
struct tsch_asn_t asn;
struct tsch_link *link;
union {
char message[48];

View file

@ -66,7 +66,7 @@
/* Construct enhanced ACK packet and return ACK length */
int
tsch_packet_create_eack(uint8_t *buf, int buf_size,
linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack)
const linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack)
{
int ret;
uint8_t curr_len = 0;
@ -125,7 +125,7 @@ tsch_packet_create_eack(uint8_t *buf, int buf_size,
/* Parse enhanced ACK packet, extract drift and nack */
int
tsch_packet_parse_eack(const uint8_t *buf, int buf_size,
uint8_t seqno, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len)
uint8_t seqno, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len)
{
uint8_t curr_len = 0;
int ret;
@ -155,8 +155,8 @@ tsch_packet_parse_eack(const uint8_t *buf, int buf_size,
/* Check destination address (if any) */
if(frame802154_extract_linkaddr(frame, NULL, &dest) == 0 ||
(!linkaddr_cmp(&dest, &linkaddr_node_addr)
&& !linkaddr_cmp(&dest, &linkaddr_null))) {
(!linkaddr_cmp(&dest, &linkaddr_node_addr)
&& !linkaddr_cmp(&dest, &linkaddr_null))) {
return 0;
}
@ -190,7 +190,7 @@ tsch_packet_parse_eack(const uint8_t *buf, int buf_size,
/* Create an EB packet */
int
tsch_packet_create_eb(uint8_t *buf, int buf_size,
uint8_t *hdr_len, uint8_t *tsch_sync_ie_offset)
uint8_t *hdr_len, uint8_t *tsch_sync_ie_offset)
{
int ret = 0;
uint8_t curr_len = 0;
@ -338,7 +338,7 @@ int
tsch_packet_update_eb(uint8_t *buf, int buf_size, uint8_t tsch_sync_ie_offset)
{
struct ieee802154_ies ies;
ies.ie_asn = current_asn;
ies.ie_asn = tsch_current_asn;
ies.ie_join_priority = tsch_join_priority;
frame80215e_create_ie_tsch_synchronization(buf+tsch_sync_ie_offset, buf_size-tsch_sync_ie_offset, &ies);
return 1;
@ -347,7 +347,7 @@ tsch_packet_update_eb(uint8_t *buf, int buf_size, uint8_t tsch_sync_ie_offset)
/* Parse a IEEE 802.15.4e TSCH Enhanced Beacon (EB) */
int
tsch_packet_parse_eb(const uint8_t *buf, int buf_size,
frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len, int frame_without_mic)
frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len, int frame_without_mic)
{
uint8_t curr_len = 0;
int ret;

View file

@ -88,7 +88,7 @@ by default, useful in case of duplicate seqno */
/* Construct enhanced ACK packet and return ACK length */
int tsch_packet_create_eack(uint8_t *buf, int buf_size,
linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack);
const linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack);
/* Parse enhanced ACK packet, extract drift and nack */
int tsch_packet_parse_eack(const uint8_t *buf, int buf_size,
uint8_t seqno, frame802154_t *frame, struct ieee802154_ies *ies, uint8_t *hdr_len);

View file

@ -48,6 +48,10 @@
#include "net/linkaddr.h"
#include "net/mac/tsch/tsch-asn.h"
#include "net/mac/tsch/tsch-conf.h"
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
/************ Types ***********/
@ -76,12 +80,12 @@ extern const linkaddr_t tsch_broadcast_address;
/* The address we use to identify EB queue */
extern const linkaddr_t tsch_eb_address;
/* The current Absolute Slot Number (ASN) */
extern struct asn_t current_asn;
extern struct tsch_asn_t tsch_current_asn;
extern uint8_t tsch_join_priority;
extern struct tsch_link *current_link;
/* TSCH channel hopping sequence */
extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
extern struct asn_divisor_t tsch_hopping_sequence_length;
extern struct tsch_asn_divisor_t tsch_hopping_sequence_length;
/* TSCH timeslot timing (in rtimer ticks) */
extern rtimer_clock_t tsch_timing[tsch_ts_elements_count];
@ -109,7 +113,14 @@ void tsch_disassociate(void);
#define TSCH_CLOCK_TO_SLOTS(c, timeslot_length) (TSCH_CLOCK_TO_TICKS(c) / timeslot_length)
/* Wait for a condition with timeout t0+offset. */
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) { \
simProcessRunValue = 1; \
cooja_mt_yield(); \
};
#else
#define BUSYWAIT_UNTIL_ABS(cond, t0, offset) \
while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (offset))) ;
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
#endif /* __TSCH_PRIVATE_H__ */

View file

@ -163,6 +163,13 @@ tsch_queue_update_time_source(const linkaddr_t *new_addr)
/* Update time source */
if(new_time_src != NULL) {
new_time_src->is_time_source = 1;
/* (Re)set keep-alive timeout */
tsch_set_ka_timeout(TSCH_KEEPALIVE_TIMEOUT);
/* Start sending keepalives */
tsch_schedule_keepalive();
} else {
/* Stop sending keepalives */
tsch_set_ka_timeout(0);
}
if(old_time_src != NULL) {

View file

@ -85,7 +85,7 @@ tsch_rpl_callback_new_dio_interval(uint8_t dio_interval)
tsch_set_coordinator(1);
}
/* Set EB period */
tsch_set_eb_period(TSCH_EB_PERIOD);
tsch_set_eb_period((CLOCK_SECOND * 1UL << dag->instance->dio_intcurrent) / 1000);
/* Set join priority based on RPL rank */
tsch_set_join_priority(DAG_RANK(dag->rank, dag->instance) - 1);
} else {

View file

@ -87,7 +87,7 @@ tsch_schedule_add_slotframe(uint16_t handle, uint16_t size)
if(sf != NULL) {
/* Initialize the slotframe */
sf->handle = handle;
ASN_DIVISOR_INIT(sf->size, size);
TSCH_ASN_DIVISOR_INIT(sf->size, size);
LIST_STRUCT_INIT(sf, links_list);
/* Add the slotframe to the global list */
list_add(slotframe_list, sf);
@ -310,7 +310,7 @@ tsch_schedule_get_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t ti
/*---------------------------------------------------------------------------*/
/* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */
struct tsch_link *
tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset,
tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset,
struct tsch_link **backup_link)
{
uint16_t time_to_curr_best = 0;
@ -324,7 +324,7 @@ tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset,
/* For each slotframe, look for the earliest occurring link */
while(sf != NULL) {
/* Get timeslot from ASN, given the slotframe length */
uint16_t timeslot = ASN_MOD(*asn, sf->size);
uint16_t timeslot = TSCH_ASN_MOD(*asn, sf->size);
struct tsch_link *l = list_head(sf->links_list);
while(l != NULL) {
uint16_t time_to_timeslot =

View file

@ -119,7 +119,7 @@ struct tsch_slotframe {
uint16_t handle;
/* Number of timeslots in the slotframe.
* Stored as struct asn_divisor_t because we often need ASN%size */
struct asn_divisor_t size;
struct tsch_asn_divisor_t size;
/* List of links belonging to this slotframe */
LIST_STRUCT(links_list);
};
@ -158,7 +158,7 @@ int tsch_schedule_remove_link(struct tsch_slotframe *slotframe, struct tsch_link
int tsch_schedule_remove_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot);
/* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */
struct tsch_link * tsch_schedule_get_next_active_link(struct asn_t *asn, uint16_t *time_offset,
struct tsch_link * tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset,
struct tsch_link **backup_link);
#endif /* __TSCH_SCHEDULE_H__ */

View file

@ -73,7 +73,7 @@ static aes_key keys[] = {
/*---------------------------------------------------------------------------*/
static void
tsch_security_init_nonce(uint8_t *nonce,
const linkaddr_t *sender, struct asn_t *asn)
const linkaddr_t *sender, struct tsch_asn_t *asn)
{
memcpy(nonce, sender, 8);
nonce[8] = asn->ms1b;
@ -120,11 +120,12 @@ tsch_security_check_level(const frame802154_t *frame)
required_key_index = TSCH_SECURITY_KEY_INDEX_OTHER;
break;
}
return frame->aux_hdr.security_control.security_level == required_security_level
&& frame->aux_hdr.key_index == required_key_index;
return ((frame->aux_hdr.security_control.security_level ==
required_security_level) &&
frame->aux_hdr.key_index == required_key_index);
}
/*---------------------------------------------------------------------------*/
int
unsigned int
tsch_security_mic_len(const frame802154_t *frame)
{
if(frame != NULL && frame->fcf.security_enabled) {
@ -134,9 +135,9 @@ tsch_security_mic_len(const frame802154_t *frame)
}
}
/*---------------------------------------------------------------------------*/
int
unsigned int
tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
int hdrlen, int datalen, struct asn_t *asn)
int hdrlen, int datalen, struct tsch_asn_t *asn)
{
frame802154_t frame;
uint8_t key_index = 0;
@ -159,7 +160,7 @@ tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
if(!frame.fcf.security_enabled) {
/* Security is not enabled for this frame, we're done */
return 1;
return 0;
}
/* Read security key index */
@ -190,17 +191,17 @@ tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
CCM_STAR.set_key(keys[key_index - 1]);
CCM_STAR.aead(nonce,
outbuf + a_len, m_len,
outbuf, a_len,
outbuf + hdrlen + datalen, mic_len, 1
);
outbuf + a_len, m_len,
outbuf, a_len,
outbuf + hdrlen + datalen, mic_len, 1);
return mic_len;
}
/*---------------------------------------------------------------------------*/
int
unsigned int
tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen,
const frame802154_t *frame, const linkaddr_t *sender, struct asn_t *asn)
const frame802154_t *frame, const linkaddr_t *sender,
struct tsch_asn_t *asn)
{
uint8_t generated_mic[16];
uint8_t key_index = 0;
@ -248,10 +249,9 @@ tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen,
CCM_STAR.set_key(keys[key_index - 1]);
CCM_STAR.aead(nonce,
(uint8_t *)hdr + a_len, m_len,
(uint8_t *)hdr, a_len,
generated_mic, mic_len, 0
);
(uint8_t *)hdr + a_len, m_len,
(uint8_t *)hdr, a_len,
generated_mic, mic_len, 0);
if(mic_len > 0 && memcmp(generated_mic, hdr + hdrlen + datalen, mic_len) != 0) {
return 0;

View file

@ -118,11 +118,28 @@
typedef uint8_t aes_key[16];
/********** Functions *********/
/**
* \brief Return MIC length
* \return The length of MIC (>= 0)
*/
unsigned int tsch_security_mic_len(const frame802154_t *frame);
int tsch_security_mic_len(const frame802154_t *frame);
int tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
int hdrlen, int datalen, struct asn_t *asn);
int tsch_security_parse_frame(const uint8_t *hdr, int hdrlen, int datalen,
const frame802154_t *frame, const linkaddr_t *sender, struct asn_t *asn);
/**
* \brief Protect a frame with encryption and/or MIC
* \return The length of a generated MIC (>= 0)
*/
unsigned int tsch_security_secure_frame(uint8_t *hdr, uint8_t *outbuf,
int hdrlen, int datalen,
struct tsch_asn_t *asn);
/**
* \brief Parse and check a frame protected with encryption and/or MIC
* \retval 0 On error or security check failure (insecure frame)
* \retval 1 On success or no need for security check (good frame)
*/
unsigned int tsch_security_parse_frame(const uint8_t *hdr, int hdrlen,
int datalen, const frame802154_t *frame,
const linkaddr_t *sender,
struct tsch_asn_t *asn);
#endif /* __TSCH_SECURITY_H__ */

View file

@ -54,6 +54,10 @@
#include "net/mac/tsch/tsch-packet.h"
#include "net/mac/tsch/tsch-security.h"
#include "net/mac/tsch/tsch-adaptive-timesync.h"
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
#if TSCH_LOG_LEVEL >= 1
#define DEBUG DEBUG_PRINT
@ -104,7 +108,10 @@
#if RTIMER_SECOND < (32 * 1024)
#error "TSCH: RTIMER_SECOND < (32 * 1024)"
#endif
#if RTIMER_SECOND >= 200000
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
/* Use 0 usec guard time for Cooja Mote with a 1 MHz Rtimer*/
#define RTIMER_GUARD 0u
#elif RTIMER_SECOND >= 200000
#define RTIMER_GUARD (RTIMER_SECOND / 100000)
#else
#define RTIMER_GUARD 2u
@ -132,7 +139,7 @@ struct ringbufindex input_ringbuf;
struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
/* Last time we received Sync-IE (ACK or data packet from a time source) */
static struct asn_t last_sync_asn;
static struct tsch_asn_t last_sync_asn;
/* A global lock for manipulating data structures safely from outside of interrupt */
static volatile int tsch_locked = 0;
@ -200,7 +207,12 @@ tsch_get_lock(void)
if(tsch_in_slot_operation) {
busy_wait = 1;
busy_wait_time = RTIMER_NOW();
while(tsch_in_slot_operation);
while(tsch_in_slot_operation) {
#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64
simProcessRunValue = 1;
cooja_mt_yield();
#endif /* CONTIKI_TARGET_COOJA || CONTIKI_TARGET_COOJA_IP64 */
}
busy_wait_time = RTIMER_NOW() - busy_wait_time;
}
if(!tsch_locked) {
@ -236,9 +248,9 @@ tsch_release_lock(void)
/* Return channel from ASN and channel offset */
uint8_t
tsch_calculate_channel(struct asn_t *asn, uint8_t channel_offset)
tsch_calculate_channel(struct tsch_asn_t *asn, uint8_t channel_offset)
{
uint16_t index_of_0 = ASN_MOD(*asn, tsch_hopping_sequence_length);
uint16_t index_of_0 = TSCH_ASN_MOD(*asn, tsch_hopping_sequence_length);
uint16_t index_of_offset = (index_of_0 + channel_offset) % tsch_hopping_sequence_length.val;
return tsch_hopping_sequence[index_of_offset];
}
@ -518,7 +530,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
* the original untouched. This is to allow for future retransmissions. */
int with_encryption = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL) & 0x4;
packet_len += tsch_security_secure_frame(packet, with_encryption ? encrypted_packet : packet, current_packet->header_len,
packet_len - current_packet->header_len, &current_asn);
packet_len - current_packet->header_len, &tsch_current_asn);
if(with_encryption) {
packet = encrypted_packet;
}
@ -615,7 +627,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
#if LLSEC802154_ENABLED
if(ack_len != 0) {
if(!tsch_security_parse_frame(ackbuf, ack_hdrlen, ack_len - ack_hdrlen - tsch_security_mic_len(&frame),
&frame, &current_neighbor->addr, &current_asn)) {
&frame, &current_neighbor->addr, &tsch_current_asn)) {
TSCH_LOG_ADD(tsch_log_message,
snprintf(log->message, sizeof(log->message),
"!failed to authenticate ACK"));
@ -632,7 +644,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
if(ack_len != 0) {
if(is_time_source) {
int32_t eack_time_correction = US_TO_RTIMERTICKS(ack_ies.ie_time_correction);
int32_t since_last_timesync = ASN_DIFF(current_asn, last_sync_asn);
int32_t since_last_timesync = TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn);
if(eack_time_correction > SYNC_IE_BOUND) {
drift_correction = SYNC_IE_BOUND;
} else if(eack_time_correction < -SYNC_IE_BOUND) {
@ -649,7 +661,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
is_drift_correction_used = 1;
tsch_timesync_update(current_neighbor, since_last_timesync, drift_correction);
/* Keep track of sync time */
last_sync_asn = current_asn;
last_sync_asn = tsch_current_asn;
tsch_schedule_keepalive();
}
mac_tx_status = MAC_TX_OK;
@ -781,7 +793,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
/* Read packet */
current_input->len = NETSTACK_RADIO.read((void *)current_input->payload, TSCH_PACKET_MAX_LEN);
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi);
current_input->rx_asn = current_asn;
current_input->rx_asn = tsch_current_asn;
current_input->rssi = (signed)radio_last_rssi;
current_input->channel = current_channel;
header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame);
@ -801,7 +813,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
if(frame_valid) {
if(tsch_security_parse_frame(
current_input->payload, header_len, current_input->len - header_len - tsch_security_mic_len(&frame),
&frame, &source_address, &current_asn)) {
&frame, &source_address, &tsch_current_asn)) {
current_input->len -= tsch_security_mic_len(&frame);
} else {
TSCH_LOG_ADD(tsch_log_message,
@ -849,30 +861,32 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
ack_len = tsch_packet_create_eack(ack_buf, sizeof(ack_buf),
&source_address, frame.seq, (int16_t)RTIMERTICKS_TO_US(estimated_drift), do_nack);
if(ack_len > 0) {
#if LLSEC802154_ENABLED
if(tsch_is_pan_secured) {
/* Secure ACK frame. There is only header and header IEs, therefore data len == 0. */
ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, &current_asn);
}
if(tsch_is_pan_secured) {
/* Secure ACK frame. There is only header and header IEs, therefore data len == 0. */
ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, &tsch_current_asn);
}
#endif /* LLSEC802154_ENABLED */
/* Copy to radio buffer */
NETSTACK_RADIO.prepare((const void *)ack_buf, ack_len);
/* Copy to radio buffer */
NETSTACK_RADIO.prepare((const void *)ack_buf, ack_len);
/* Wait for time to ACK and transmit ACK */
TSCH_SCHEDULE_AND_YIELD(pt, t, rx_start_time,
packet_duration + tsch_timing[tsch_ts_tx_ack_delay] - RADIO_DELAY_BEFORE_TX, "RxBeforeAck");
TSCH_DEBUG_RX_EVENT();
NETSTACK_RADIO.transmit(ack_len);
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
/* Wait for time to ACK and transmit ACK */
TSCH_SCHEDULE_AND_YIELD(pt, t, rx_start_time,
packet_duration + tsch_timing[tsch_ts_tx_ack_delay] - RADIO_DELAY_BEFORE_TX, "RxBeforeAck");
TSCH_DEBUG_RX_EVENT();
NETSTACK_RADIO.transmit(ack_len);
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
}
}
/* If the sender is a time source, proceed to clock drift compensation */
n = tsch_queue_get_nbr(&source_address);
if(n != NULL && n->is_time_source) {
int32_t since_last_timesync = ASN_DIFF(current_asn, last_sync_asn);
int32_t since_last_timesync = TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn);
/* Keep track of last sync time */
last_sync_asn = current_asn;
last_sync_asn = tsch_current_asn;
/* Save estimated drift */
drift_correction = -estimated_drift;
is_drift_correction_used = 1;
@ -958,7 +972,7 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX);
if(is_active_slot) {
/* Hop channel */
current_channel = tsch_calculate_channel(&current_asn, current_link->channel_offset);
current_channel = tsch_calculate_channel(&tsch_current_asn, current_link->channel_offset);
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
/* Turn the radio on already here if configured so; necessary for radios with slow startup */
tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT);
@ -984,12 +998,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
/* End of slot operation, schedule next slot or resynchronize */
/* Do we need to resynchronize? i.e., wait for EB again */
if(!tsch_is_coordinator && (ASN_DIFF(current_asn, last_sync_asn) >
if(!tsch_is_coordinator && (TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn) >
(100 * TSCH_CLOCK_TO_SLOTS(TSCH_DESYNC_THRESHOLD / 100, tsch_timing[tsch_ts_timeslot_length])))) {
TSCH_LOG_ADD(tsch_log_message,
snprintf(log->message, sizeof(log->message),
"! leaving the network, last sync %u",
(unsigned)ASN_DIFF(current_asn, last_sync_asn));
(unsigned)TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn));
);
last_timesource_neighbor = NULL;
tsch_disassociate();
@ -1011,14 +1025,14 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
}
/* Get next active link */
current_link = tsch_schedule_get_next_active_link(&current_asn, &timeslot_diff, &backup_link);
current_link = tsch_schedule_get_next_active_link(&tsch_current_asn, &timeslot_diff, &backup_link);
if(current_link == NULL) {
/* There is no next link. Fall back to default
* behavior: wake up at the next slot. */
timeslot_diff = 1;
}
/* Update ASN */
ASN_INC(current_asn, timeslot_diff);
TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
/* Time to next wake up */
time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length] + drift_correction;
drift_correction = 0;
@ -1049,14 +1063,14 @@ tsch_slot_operation_start(void)
do {
uint16_t timeslot_diff;
/* Get next active link */
current_link = tsch_schedule_get_next_active_link(&current_asn, &timeslot_diff, &backup_link);
current_link = tsch_schedule_get_next_active_link(&tsch_current_asn, &timeslot_diff, &backup_link);
if(current_link == NULL) {
/* There is no next link. Fall back to default
* behavior: wake up at the next slot. */
timeslot_diff = 1;
}
/* Update ASN */
ASN_INC(current_asn, timeslot_diff);
TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
/* Time to next wake up */
time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length];
/* Update current slot start */
@ -1068,11 +1082,11 @@ tsch_slot_operation_start(void)
/* Start actual slot operation */
void
tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
struct asn_t *next_slot_asn)
struct tsch_asn_t *next_slot_asn)
{
current_slot_start = next_slot_start;
current_asn = *next_slot_asn;
last_sync_asn = current_asn;
tsch_current_asn = *next_slot_asn;
last_sync_asn = tsch_current_asn;
current_link = NULL;
}
/*---------------------------------------------------------------------------*/

View file

@ -87,7 +87,7 @@ int TSCH_CALLBACK_DO_NACK(struct tsch_link *link, linkaddr_t *src, linkaddr_t *d
/* Stores data about an incoming packet */
struct input_packet {
uint8_t payload[TSCH_PACKET_MAX_LEN]; /* Packet payload */
struct asn_t rx_asn; /* ASN when the packet was received */
struct tsch_asn_t rx_asn; /* ASN when the packet was received */
int len; /* Packet len */
int16_t rssi; /* RSSI for this packet */
uint8_t channel; /* Channel we received the packet on */
@ -107,7 +107,7 @@ extern struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
/********** Functions *********/
/* Returns a 802.15.4 channel from an ASN and channel offset */
uint8_t tsch_calculate_channel(struct asn_t *asn, uint8_t channel_offset);
uint8_t tsch_calculate_channel(struct tsch_asn_t *asn, uint8_t channel_offset);
/* Is TSCH locked? */
int tsch_is_locked(void);
/* Lock TSCH (no link operation) */
@ -117,7 +117,7 @@ void tsch_release_lock(void);
/* Set global time before starting slot operation,
* with a rtimer time and an ASN */
void tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
struct asn_t *next_slot_asn);
struct tsch_asn_t *next_slot_asn);
/* Start actual slot operation */
void tsch_slot_operation_start(void);

View file

@ -90,7 +90,7 @@ NBR_TABLE(struct eb_stat, eb_stats);
/* TSCH channel hopping sequence */
uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
struct asn_divisor_t tsch_hopping_sequence_length;
struct tsch_asn_divisor_t tsch_hopping_sequence_length;
/* Default TSCH timeslot timing (in micro-second) */
static const uint16_t tsch_default_timing_us[tsch_ts_elements_count] = {
@ -131,7 +131,7 @@ int tsch_is_associated = 0;
/* Is the PAN running link-layer security? */
int tsch_is_pan_secured = LLSEC802154_ENABLED;
/* The current Absolute Slot Number (ASN) */
struct asn_t current_asn;
struct tsch_asn_t tsch_current_asn;
/* Device rank or join priority:
* For PAN coordinator: 0 -- lower is better */
uint8_t tsch_join_priority;
@ -139,6 +139,8 @@ uint8_t tsch_join_priority;
static uint8_t tsch_packet_seqno = 0;
/* Current period for EB output */
static clock_time_t tsch_current_eb_period;
/* Current period for keepalive output */
static clock_time_t tsch_current_ka_timeout;
/* timer for sending keepalive messages */
static struct ctimer keepalive_timer;
@ -175,9 +177,15 @@ tsch_set_join_priority(uint8_t jp)
}
/*---------------------------------------------------------------------------*/
void
tsch_set_ka_timeout(uint32_t timeout)
{
tsch_current_ka_timeout = timeout;
}
/*---------------------------------------------------------------------------*/
void
tsch_set_eb_period(uint32_t period)
{
tsch_current_eb_period = period;
tsch_current_eb_period = MIN(period, TSCH_MAX_EB_PERIOD);
}
/*---------------------------------------------------------------------------*/
static void
@ -194,7 +202,7 @@ tsch_reset(void)
tsch_queue_update_time_source(NULL);
/* Initialize global variables */
tsch_join_priority = 0xff;
ASN_INIT(current_asn, 0, 0);
TSCH_ASN_INIT(tsch_current_asn, 0, 0);
current_link = NULL;
/* Reset timeslot timing to defaults */
for(i = 0; i < tsch_ts_elements_count; i++) {
@ -244,10 +252,10 @@ keepalive_send()
void
tsch_schedule_keepalive()
{
/* Pick a delay in the range [TSCH_KEEPALIVE_TIMEOUT*0.9, TSCH_KEEPALIVE_TIMEOUT[ */
if(!tsch_is_coordinator && tsch_is_associated) {
unsigned long delay = (TSCH_KEEPALIVE_TIMEOUT - TSCH_KEEPALIVE_TIMEOUT / 10)
+ random_rand() % (TSCH_KEEPALIVE_TIMEOUT / 10);
/* Pick a delay in the range [tsch_current_ka_timeout*0.9, tsch_current_ka_timeout[ */
if(!tsch_is_coordinator && tsch_is_associated && tsch_current_ka_timeout > 0) {
unsigned long delay = (tsch_current_ka_timeout - tsch_current_ka_timeout / 10)
+ random_rand() % (tsch_current_ka_timeout / 10);
ctimer_set(&keepalive_timer, delay, keepalive_send, NULL);
}
}
@ -302,7 +310,7 @@ eb_input(struct input_packet *current_input)
/* Did the EB come from our time source? */
if(n != NULL && linkaddr_cmp((linkaddr_t *)&frame.src_addr, &n->addr)) {
/* Check for ASN drift */
int32_t asn_diff = ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn);
int32_t asn_diff = TSCH_ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn);
if(asn_diff != 0) {
/* We disagree with our time source's ASN -- leave the network */
PRINTF("TSCH:! ASN drifted by %ld, leaving the network\n", asn_diff);
@ -393,7 +401,7 @@ tsch_start_coordinator(void)
frame802154_set_pan_id(IEEE802154_PANID);
/* Initialize hopping sequence as default */
memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
#if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL
tsch_schedule_create_minimal();
#endif
@ -402,10 +410,10 @@ tsch_start_coordinator(void)
tsch_join_priority = 0;
PRINTF("TSCH: starting as coordinator, PAN ID %x, asn-%x.%lx\n",
frame802154_get_pan_id(), current_asn.ms1b, current_asn.ls4b);
frame802154_get_pan_id(), tsch_current_asn.ms1b, tsch_current_asn.ls4b);
/* Start slot operation */
tsch_slot_operation_sync(RTIMER_NOW(), &current_asn);
tsch_slot_operation_sync(RTIMER_NOW(), &tsch_current_asn);
}
/*---------------------------------------------------------------------------*/
/* Leave the TSCH network */
@ -434,7 +442,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
return 0;
}
current_asn = ies.ie_asn;
tsch_current_asn = ies.ie_asn;
tsch_join_priority = ies.ie_join_priority + 1;
#if TSCH_JOIN_SECURED_ONLY
@ -447,7 +455,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
#if LLSEC802154_ENABLED
if(!tsch_security_parse_frame(input_eb->payload, hdrlen,
input_eb->len - hdrlen - tsch_security_mic_len(&frame),
&frame, (linkaddr_t*)&frame.src_addr, &current_asn)) {
&frame, (linkaddr_t*)&frame.src_addr, &tsch_current_asn)) {
PRINTF("TSCH:! parse_eb: failed to authenticate\n");
return 0;
}
@ -486,11 +494,11 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
/* TSCH hopping sequence */
if(ies.ie_channel_hopping_sequence_id == 0) {
memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
} else {
if(ies.ie_hopping_sequence_len <= sizeof(tsch_hopping_sequence)) {
memcpy(tsch_hopping_sequence, ies.ie_hopping_sequence_list, ies.ie_hopping_sequence_len);
ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len);
TSCH_ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len);
} else {
PRINTF("TSCH:! parse_eb: hopping sequence too long (%u)\n", ies.ie_hopping_sequence_len);
return 0;
@ -501,10 +509,10 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
/* Divide by 4k and multiply again to avoid integer overflow */
uint32_t expected_asn = 4096 * TSCH_CLOCK_TO_SLOTS(clock_time() / 4096, tsch_timing_timeslot_length); /* Expected ASN based on our current time*/
int32_t asn_threshold = TSCH_CHECK_TIME_AT_ASSOCIATION * 60ul * TSCH_CLOCK_TO_SLOTS(CLOCK_SECOND, tsch_timing_timeslot_length);
int32_t asn_diff = (int32_t)current_asn.ls4b - expected_asn;
int32_t asn_diff = (int32_t)tsch_current_asn.ls4b - expected_asn;
if(asn_diff > asn_threshold) {
PRINTF("TSCH:! EB ASN rejected %lx %lx %ld\n",
current_asn.ls4b, expected_asn, asn_diff);
tsch_current_asn.ls4b, expected_asn, asn_diff);
return 0;
}
#endif
@ -554,7 +562,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
frame802154_set_pan_id(frame.src_pid);
/* Synchronize on EB */
tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], &current_asn);
tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], &tsch_current_asn);
/* Update global flags */
tsch_is_associated = 1;
@ -570,7 +578,7 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
PRINTF("TSCH: association done, sec %u, PAN ID %x, asn-%x.%lx, jp %u, timeslot id %u, hopping id %u, slotframe len %u with %u links, from ",
tsch_is_pan_secured,
frame.src_pid,
current_asn.ms1b, current_asn.ls4b, tsch_join_priority,
tsch_current_asn.ms1b, tsch_current_asn.ls4b, tsch_join_priority,
ies.ie_tsch_timeslot_id,
ies.ie_channel_hopping_sequence_id,
ies.ie_tsch_slotframe_and_link.slotframe_size,
@ -601,7 +609,7 @@ PT_THREAD(tsch_scan(struct pt *pt))
/* Time when we started scanning on current_channel */
static clock_time_t current_channel_since;
ASN_INIT(current_asn, 0, 0);
TSCH_ASN_INIT(tsch_current_asn, 0, 0);
etimer_set(&scan_timer, CLOCK_SECOND / TSCH_ASSOCIATION_POLL_FREQUENCY);
current_channel_since = clock_time();
@ -741,7 +749,7 @@ PROCESS_THREAD(tsch_send_eb_process, ev, data)
#endif /* LLSEC802154_ENABLED */
eb_len = tsch_packet_create_eb(packetbuf_dataptr(), PACKETBUF_SIZE,
&hdr_len, &tsch_sync_ie_offset);
if(eb_len != 0) {
if(eb_len > 0) {
struct tsch_packet *p;
packetbuf_set_datalen(eb_len);
/* Enqueue EB packet */
@ -902,6 +910,15 @@ send_packet(mac_callback_t sent, void *ptr)
packet_count_before = tsch_queue_packet_count(addr);
#if !NETSTACK_CONF_BRIDGE_MODE
/*
* In the Contiki stack, the source address of a frame is set at the RDC
* layer. Since TSCH doesn't use any RDC protocol and bypasses the layer to
* transmit a frame, it should set the source address by itself.
*/
packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
#endif
if((hdr_len = NETSTACK_FRAMER.create()) < 0) {
PRINTF("TSCH:! can't send packet due to framer error\n");
ret = MAC_TX_ERR;

View file

@ -49,18 +49,33 @@
#define TSCH_KEEPALIVE_TIMEOUT (12 * CLOCK_SECOND)
#endif
/* With TSCH_ADAPTIVE_TIMESYNC enabled: keep-alive timeout used after reaching
* accurate drift compensation. */
#ifdef TSCH_CONF_MAX_KEEPALIVE_TIMEOUT
#define TSCH_MAX_KEEPALIVE_TIMEOUT TSCH_CONF_MAX_KEEPALIVE_TIMEOUT
#else
#define TSCH_MAX_KEEPALIVE_TIMEOUT (60 * CLOCK_SECOND)
#endif
/* Max time without synchronization before leaving the PAN */
#ifdef TSCH_CONF_DESYNC_THRESHOLD
#define TSCH_DESYNC_THRESHOLD TSCH_CONF_DESYNC_THRESHOLD
#else
#define TSCH_DESYNC_THRESHOLD (4 * TSCH_KEEPALIVE_TIMEOUT)
#define TSCH_DESYNC_THRESHOLD (2 * TSCH_MAX_KEEPALIVE_TIMEOUT)
#endif
/* Period between two consecutive EBs */
#ifdef TSCH_CONF_EB_PERIOD
#define TSCH_EB_PERIOD TSCH_CONF_EB_PERIOD
#else
#define TSCH_EB_PERIOD (4 * CLOCK_SECOND)
#define TSCH_EB_PERIOD (16 * CLOCK_SECOND)
#endif
/* Max Period between two consecutive EBs */
#ifdef TSCH_CONF_MAX_EB_PERIOD
#define TSCH_MAX_EB_PERIOD TSCH_CONF_MAX_EB_PERIOD
#else
#define TSCH_MAX_EB_PERIOD (50 * CLOCK_SECOND)
#endif
/* Max acceptable join priority */
@ -157,8 +172,10 @@ extern const struct mac_driver tschmac_driver;
/* The the TSCH join priority */
void tsch_set_join_priority(uint8_t jp);
/* The the period at which EBs are sent */
/* The period at which EBs are sent */
void tsch_set_eb_period(uint32_t period);
/* The keep-alive timeout */
void tsch_set_ka_timeout(uint32_t timeout);
/* Set the node as PAN coordinator */
void tsch_set_coordinator(int enable);
/* Set the pan as secured or not */