Added Orchestra, an autonomous scheduler for TSCH exploiting the local RPL state to maintain slotframes and links
This commit is contained in:
parent
20c97367a9
commit
bc1e27cab7
8 changed files with 793 additions and 0 deletions
1
apps/orchestra/Makefile.orchestra
Normal file
1
apps/orchestra/Makefile.orchestra
Normal file
|
@ -0,0 +1 @@
|
|||
orchestra_src = orchestra.c orchestra-rule-default-common.c orchestra-rule-eb-per-time-source.c orchestra-rule-unicast-per-neighbor.c
|
51
apps/orchestra/README.md
Normal file
51
apps/orchestra/README.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Orchestra
|
||||
|
||||
## Overview
|
||||
|
||||
Orchestra is an autonomous scheduling solution for TSCH, where nodes maintain
|
||||
their own schedule solely based on their local RPL state. There is no centralized
|
||||
scheduler nor negociatoin with neighbors, i.e. no traffic overhead. The default
|
||||
Orchestra rules can be used out-of-box in any RPL network, reducing contention
|
||||
to a low level. Orchestra is described and evaluated in
|
||||
[*Orchestra: Robust Mesh Networks Through Autonomously Scheduled TSCH*](http://www.simonduquennoy.net/papers/duquennoy15orchestra.pdf), ACM SenSys'15.
|
||||
|
||||
## Requirements
|
||||
|
||||
Orchestra requires a system running TSCH and RPL.
|
||||
For sender-based unicast slots (`ORCHESTRA_UNICAST_SENDER_BASED`), it requires
|
||||
RPL with downwards routing enabled (relies on DAO).
|
||||
|
||||
## Getting Started
|
||||
|
||||
To use Orchestra, add a couple global definitions, e.g in your `project-conf.h` file.
|
||||
|
||||
Disable 6TiSCH minimal schedule:
|
||||
|
||||
`#define TSCH_SCHEDULE_CONF_WITH_6TISCH_MINIMAL 0`
|
||||
|
||||
Enable TSCH link selector (allows Orchestra to assign TSCH links to outgoing packets):
|
||||
|
||||
`#define TSCH_CONF_WITH_LINK_SELECTOR 1`
|
||||
|
||||
Set up the following callbacks:
|
||||
|
||||
```
|
||||
#define TSCH_CALLBACK_NEW_TIME_SOURCE orchestra_callback_new_time_source
|
||||
#define TSCH_CALLBACK_PACKET_READY orchestra_callback_packet_ready
|
||||
#define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added
|
||||
#define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed
|
||||
```
|
||||
|
||||
To use Orchestra, fist add it to your makefile `APPS` with `APPS += orchestra`.
|
||||
|
||||
Finally:
|
||||
* add Orchestra to your makefile `APPS` with `APPS += orchestra`;
|
||||
* start Orchestra by calling `orchestra_init()` from your application, after
|
||||
including `#include "orchestra.h"`.
|
||||
|
||||
## Configuration
|
||||
|
||||
Orchestra comes with a number of pre-installed rules, `orchestra-rule-*.c`.
|
||||
You can define your own by using any of these as a template.
|
||||
A default Orchestra configuration is described in `orchestra-conf.h`, define your own
|
||||
`ORCHESTRA_CONF_*` macros to override modify the rule set and change rules configuration.
|
105
apps/orchestra/orchestra-conf.h
Normal file
105
apps/orchestra/orchestra-conf.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Orchestra configuration
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __ORCHESTRA_CONF_H__
|
||||
#define __ORCHESTRA_CONF_H__
|
||||
|
||||
#ifdef ORCHESTRA_CONF_RULES
|
||||
#define ORCHESTRA_RULES ORCHESTRA_CONF_RULES
|
||||
#else /* ORCHESTRA_CONF_RULES */
|
||||
/* A default configuration with:
|
||||
* - a sender-based slotframe for EB transmission
|
||||
* - a sender-based or receiver-based slotframe for unicast to RPL parents and children
|
||||
* - a common shared slotframe for any other traffic (mostly broadcast)
|
||||
* */
|
||||
#define ORCHESTRA_RULES { &eb_per_time_source, \
|
||||
&unicast_per_neighbor, \
|
||||
&default_common, \
|
||||
}
|
||||
#endif /* ORCHESTRA_CONF_RULES */
|
||||
|
||||
/* Length of the various slotframes. Tune to balance network capacity,
|
||||
* contention, energy, latency. */
|
||||
#ifdef ORCHESTRA_CONF_EBSF_PERIOD
|
||||
#define ORCHESTRA_EBSF_PERIOD ORCHESTRA_CONF_EBSF_PERIOD
|
||||
#else /* ORCHESTRA_CONF_EBSF_PERIOD */
|
||||
#define ORCHESTRA_EBSF_PERIOD 397
|
||||
#endif /* ORCHESTRA_CONF_EBSF_PERIOD */
|
||||
|
||||
#ifdef ORCHESTRA_CONF_COMMON_SHARED_PERIOD
|
||||
#define ORCHESTRA_COMMON_SHARED_PERIOD ORCHESTRA_CONF_COMMON_SHARED_PERIOD
|
||||
#else /* ORCHESTRA_CONF_COMMON_SHARED_PERIOD */
|
||||
#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 */
|
||||
#define ORCHESTRA_UNICAST_PERIOD 17
|
||||
#endif /* ORCHESTRA_CONF_COMMON_SHARED_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
|
||||
* routing entries to keep track of children and parents. */
|
||||
#ifdef ORCHESTRA_CONF_UNICAST_SENDER_BASED
|
||||
#define ORCHESTRA_UNICAST_SENDER_BASED ORCHESTRA_CONF_UNICAST_SENDER_BASED
|
||||
#else /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
|
||||
#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) */
|
||||
#ifdef ORCHESTRA_CONF_LINKADDR_HASH
|
||||
#define ORCHESTRA_LINKADDR_HASH ORCHESTRA_CONF_LINKADDR_HASH
|
||||
#else /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
|
||||
#define ORCHESTRA_LINKADDR_HASH(addr) ((addr != NULL) ? (addr)->u8[LINKADDR_SIZE - 1] : -1)
|
||||
#endif /* ORCHESTRA_CONF_UNICAST_SENDER_BASED */
|
||||
|
||||
/* The maximum hash */
|
||||
#ifdef ORCHESTRA_CONF_MAX_HASH
|
||||
#define ORCHESTRA_MAX_HASH ORCHESTRA_CONF_MAX_HASH
|
||||
#else /* ORCHESTRA_CONF_MAX_HASH */
|
||||
#define ORCHESTRA_MAX_HASH 0x7fff
|
||||
#endif /* ORCHESTRA_CONF_MAX_HASH */
|
||||
|
||||
/* Is the "hash" function collision-free? (e.g. it maps to unique node-ids) */
|
||||
#ifdef ORCHESTRA_CONF_COLLISION_FREE_HASH
|
||||
#define ORCHESTRA_COLLISION_FREE_HASH ORCHESTRA_CONF_COLLISION_FREE_HASH
|
||||
#else /* ORCHESTRA_CONF_MAX_HASH */
|
||||
#define ORCHESTRA_CONF_COLLISION_FREE_HASH 0 /* Set to 1 if ORCHESTRA_LINKADDR_HASH returns unique hashes */
|
||||
#endif /* ORCHESTRA_CONF_MAX_HASH */
|
||||
|
||||
#endif /* __ORCHESTRA_CONF_H__ */
|
86
apps/orchestra/orchestra-rule-default-common.c
Normal file
86
apps/orchestra/orchestra-rule-default-common.c
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Orchestra: a slotframe with a single shared link, common to all nodes
|
||||
* in the network, used for unicast and broadcast.
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "orchestra.h"
|
||||
|
||||
static uint16_t slotframe_handle = 0;
|
||||
static uint16_t channel_offset = 0;
|
||||
|
||||
#if ORCHESTRA_EBSF_PERIOD > 0
|
||||
/* There is a slotframe for EBs, use this slotframe for non-EB traffic only */
|
||||
#define ORCHESTRA_COMMON_SHARED_TYPE LINK_TYPE_NORMAL
|
||||
#else
|
||||
/* There is no slotframe for EBs, use this slotframe both EB and non-EB traffic */
|
||||
#define ORCHESTRA_COMMON_SHARED_TYPE LINK_TYPE_ADVERTISING
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
select_packet(uint16_t *slotframe, uint16_t *timeslot)
|
||||
{
|
||||
/* We are the default slotframe, select anything */
|
||||
if(slotframe != NULL) {
|
||||
*slotframe = slotframe_handle;
|
||||
}
|
||||
if(timeslot != NULL) {
|
||||
*timeslot = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(uint16_t sf_handle)
|
||||
{
|
||||
slotframe_handle = sf_handle;
|
||||
channel_offset = slotframe_handle;
|
||||
/* Default slotframe: for broadcast or unicast to neighbors we
|
||||
* do not have a link to */
|
||||
struct tsch_slotframe *sf_common = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_COMMON_SHARED_PERIOD);
|
||||
tsch_schedule_add_link(sf_common,
|
||||
LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED,
|
||||
ORCHESTRA_COMMON_SHARED_TYPE, &tsch_broadcast_address,
|
||||
0, channel_offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct orchestra_rule default_common = {
|
||||
init,
|
||||
NULL,
|
||||
select_packet,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
116
apps/orchestra/orchestra-rule-eb-per-time-source.c
Normal file
116
apps/orchestra/orchestra-rule-eb-per-time-source.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
|
||||
* Orchestra: a slotframe dedicated to transmission of EBs.
|
||||
* Nodes transmit at a timeslot defined as hash(MAC) % ORCHESTRA_EBSF_PERIOD
|
||||
* Nodes listen at a timeslot defined as hash(time_source.MAC) % ORCHESTRA_EBSF_PERIOD
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "orchestra.h"
|
||||
#include "net/packetbuf.h"
|
||||
|
||||
static uint16_t slotframe_handle = 0;
|
||||
static uint16_t channel_offset = 0;
|
||||
static struct tsch_slotframe *sf_eb;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint16_t
|
||||
get_node_timeslot(const linkaddr_t *addr)
|
||||
{
|
||||
#if ORCHESTRA_EBSF_PERIOD > 0
|
||||
return ORCHESTRA_LINKADDR_HASH(addr) % ORCHESTRA_EBSF_PERIOD;
|
||||
#else
|
||||
return 0xffff;
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
select_packet(uint16_t *slotframe, uint16_t *timeslot)
|
||||
{
|
||||
/* Select EBs only */
|
||||
if(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE) == FRAME802154_BEACONFRAME) {
|
||||
if(slotframe != NULL) {
|
||||
*slotframe = slotframe_handle;
|
||||
}
|
||||
if(timeslot != NULL) {
|
||||
*timeslot = get_node_timeslot(&linkaddr_node_addr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
|
||||
{
|
||||
uint16_t old_ts = get_node_timeslot(&old->addr);
|
||||
uint16_t new_ts = get_node_timeslot(&new->addr);
|
||||
|
||||
if(new_ts == old_ts) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(old_ts != 0xffff) {
|
||||
/* Stop listening to the old time source's EBs */
|
||||
tsch_schedule_remove_link_by_timeslot(sf_eb, old_ts);
|
||||
}
|
||||
if(new_ts != 0xffff) {
|
||||
/* Listen to the time source's EBs */
|
||||
tsch_schedule_add_link(sf_eb,
|
||||
LINK_OPTION_RX,
|
||||
LINK_TYPE_ADVERTISING_ONLY, NULL,
|
||||
new_ts, 0);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(uint16_t sf_handle)
|
||||
{
|
||||
slotframe_handle = sf_handle;
|
||||
channel_offset = sf_handle;
|
||||
sf_eb = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_EBSF_PERIOD);
|
||||
/* EB link: every neighbor uses its own to avoid contention */
|
||||
tsch_schedule_add_link(sf_eb,
|
||||
LINK_OPTION_TX,
|
||||
LINK_TYPE_ADVERTISING_ONLY, &tsch_broadcast_address,
|
||||
get_node_timeslot(&linkaddr_node_addr), 0);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct orchestra_rule eb_per_time_source = {
|
||||
init,
|
||||
new_time_source,
|
||||
select_packet,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
194
apps/orchestra/orchestra-rule-unicast-per-neighbor.c
Normal file
194
apps/orchestra/orchestra-rule-unicast-per-neighbor.c
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Orchestra: a slotframe dedicated to unicast data transmission.
|
||||
* If sender-based:
|
||||
* Nodes listen at a timeslot defined as hash(MAC) % ORCHESTRA_SB_UNICAST_PERIOD
|
||||
* Nodes transmit at: for each nbr in RPL children and RPL preferred parent,
|
||||
* hash(nbr.MAC) % ORCHESTRA_SB_UNICAST_PERIOD
|
||||
* If receiver-based: the opposite
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "orchestra.h"
|
||||
#include "net/ipv6/uip-ds6-route.h"
|
||||
#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)
|
||||
#else
|
||||
#define UNICAST_SLOT_SHARED_FLAG LINK_OPTION_SHARED
|
||||
#endif
|
||||
|
||||
static uint16_t slotframe_handle = 0;
|
||||
static uint16_t channel_offset = 0;
|
||||
static struct tsch_slotframe *sf_unicast;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint16_t
|
||||
get_node_timeslot(const linkaddr_t *addr)
|
||||
{
|
||||
if(addr != NULL && ORCHESTRA_UNICAST_PERIOD > 0) {
|
||||
return ORCHESTRA_LINKADDR_HASH(addr) % ORCHESTRA_UNICAST_PERIOD;
|
||||
} else {
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
neighbor_has_uc_link(const linkaddr_t *linkaddr)
|
||||
{
|
||||
if(linkaddr != NULL && !linkaddr_cmp(linkaddr, &linkaddr_null)) {
|
||||
if((orchestra_parent_knows_us || !ORCHESTRA_UNICAST_SENDER_BASED)
|
||||
&& linkaddr_cmp(&orchestra_parent_linkaddr, linkaddr)) {
|
||||
return 1;
|
||||
}
|
||||
if(nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)linkaddr) != NULL) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
add_uc_link(const linkaddr_t *linkaddr)
|
||||
{
|
||||
if(linkaddr != NULL) {
|
||||
uint16_t timeslot = get_node_timeslot(linkaddr);
|
||||
tsch_schedule_add_link(sf_unicast,
|
||||
ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_RX : LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG,
|
||||
LINK_TYPE_NORMAL, &tsch_broadcast_address,
|
||||
timeslot, channel_offset);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
remove_uc_link(const linkaddr_t *linkaddr)
|
||||
{
|
||||
uint16_t timeslot;
|
||||
struct tsch_link *l;
|
||||
|
||||
if(linkaddr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
timeslot = get_node_timeslot(linkaddr);
|
||||
l = tsch_schedule_get_link_by_timeslot(sf_unicast, timeslot);
|
||||
if(l == NULL) {
|
||||
return;
|
||||
}
|
||||
/* Does our current parent need this timeslot? */
|
||||
if(timeslot == get_node_timeslot(&orchestra_parent_linkaddr)) {
|
||||
/* Yes, this timeslot is being used, return */
|
||||
return;
|
||||
}
|
||||
/* Does any other child need this timeslot?
|
||||
* (lookup all route next hops) */
|
||||
nbr_table_item_t *item = nbr_table_head(nbr_routes);
|
||||
while(item != NULL) {
|
||||
linkaddr_t *addr = nbr_table_get_lladdr(nbr_routes, item);
|
||||
if(timeslot == get_node_timeslot(addr)) {
|
||||
/* Yes, this timeslot is being used, return */
|
||||
return;
|
||||
}
|
||||
item = nbr_table_next(nbr_routes, item);
|
||||
}
|
||||
tsch_schedule_remove_link(sf_unicast, l);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
child_added(const linkaddr_t *linkaddr)
|
||||
{
|
||||
add_uc_link(linkaddr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
child_removed(const linkaddr_t *linkaddr)
|
||||
{
|
||||
remove_uc_link(linkaddr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
select_packet(uint16_t *slotframe, uint16_t *timeslot)
|
||||
{
|
||||
/* Select data packets we have a unicast link to */
|
||||
const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
|
||||
if(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE) == FRAME802154_DATAFRAME
|
||||
&& neighbor_has_uc_link(dest)) {
|
||||
if(slotframe != NULL) {
|
||||
*slotframe = slotframe_handle;
|
||||
}
|
||||
if(timeslot != NULL) {
|
||||
*timeslot = ORCHESTRA_UNICAST_SENDER_BASED ? get_node_timeslot(&linkaddr_node_addr) : get_node_timeslot(dest);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
|
||||
{
|
||||
if(new != old) {
|
||||
const linkaddr_t *new_addr = new != NULL ? &new->addr : NULL;
|
||||
if(new_addr != NULL) {
|
||||
linkaddr_copy(&orchestra_parent_linkaddr, new_addr);
|
||||
} else {
|
||||
linkaddr_copy(&orchestra_parent_linkaddr, &linkaddr_null);
|
||||
}
|
||||
remove_uc_link(new_addr);
|
||||
add_uc_link(new_addr);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
init(uint16_t sf_handle)
|
||||
{
|
||||
slotframe_handle = sf_handle;
|
||||
channel_offset = sf_handle;
|
||||
/* Slotframe for unicast transmissions */
|
||||
sf_unicast = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_UNICAST_PERIOD);
|
||||
uint16_t timeslot = get_node_timeslot(&linkaddr_node_addr);
|
||||
tsch_schedule_add_link(sf_unicast,
|
||||
ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG: LINK_OPTION_RX,
|
||||
LINK_TYPE_NORMAL, &tsch_broadcast_address,
|
||||
timeslot, channel_offset);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct orchestra_rule unicast_per_neighbor = {
|
||||
init,
|
||||
new_time_source,
|
||||
select_packet,
|
||||
child_added,
|
||||
child_removed,
|
||||
};
|
166
apps/orchestra/orchestra.c
Normal file
166
apps/orchestra/orchestra.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Orchestra: an autonomous scheduler for TSCH exploiting RPL state.
|
||||
* See "Orchestra: Robust Mesh Networks Through Autonomously Scheduled TSCH", ACM SenSys'15
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "orchestra.h"
|
||||
#include "net/packetbuf.h"
|
||||
#include "net/ipv6/uip-icmp6.h"
|
||||
#include "net/rpl/rpl-private.h"
|
||||
#include "net/rime/rime.h" /* Needed for so-called rime-sniffer */
|
||||
|
||||
#define DEBUG DEBUG_PRINT
|
||||
#include "net/ip/uip-debug.h"
|
||||
|
||||
/* A net-layer sniffer for packets sent and received */
|
||||
static void orchestra_packet_received(void);
|
||||
static void orchestra_packet_sent(int mac_status);
|
||||
RIME_SNIFFER(orhcestra_sniffer, orchestra_packet_received, orchestra_packet_sent);
|
||||
|
||||
/* The current RPL preferred parent's link-layer address */
|
||||
linkaddr_t orchestra_parent_linkaddr;
|
||||
/* Set to one only after getting an ACK for a DAO sent to our preferred parent */
|
||||
int orchestra_parent_knows_us = 0;
|
||||
|
||||
/* The set of Orchestra rules in use */
|
||||
const struct orchestra_rule *all_rules[] = ORCHESTRA_RULES;
|
||||
#define NUM_RULES (sizeof(all_rules) / sizeof(struct orchestra_rule *))
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
orchestra_packet_received(void)
|
||||
{
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
orchestra_packet_sent(int mac_status)
|
||||
{
|
||||
/* Check if our parent just ACKed a DAO */
|
||||
if(orchestra_parent_knows_us == 0
|
||||
&& mac_status == MAC_TX_OK
|
||||
&& packetbuf_attr(PACKETBUF_ATTR_NETWORK_ID) == UIP_PROTO_ICMP6
|
||||
&& packetbuf_attr(PACKETBUF_ATTR_CHANNEL) == (ICMP6_RPL << 8 | RPL_CODE_DAO)) {
|
||||
if(!linkaddr_cmp(&orchestra_parent_linkaddr, &linkaddr_null)
|
||||
&& linkaddr_cmp(&orchestra_parent_linkaddr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER))) {
|
||||
orchestra_parent_knows_us = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_callback_child_added(const linkaddr_t *addr)
|
||||
{
|
||||
/* Notify all Orchestra rules that a child was added */
|
||||
int i;
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->child_added != NULL) {
|
||||
all_rules[i]->child_added(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_callback_child_removed(const linkaddr_t *addr)
|
||||
{
|
||||
/* Notify all Orchestra rules that a child was removed */
|
||||
int i;
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->child_removed != NULL) {
|
||||
all_rules[i]->child_removed(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_callback_packet_ready(void)
|
||||
{
|
||||
int i;
|
||||
/* By default, use any slotframe, any timeslot */
|
||||
uint16_t slotframe = 9;
|
||||
uint16_t timeslot = 0xffff;
|
||||
|
||||
/* Loop over all rules until finding one able to handle the packet */
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->select_packet != NULL) {
|
||||
if(all_rules[i]->select_packet(&slotframe, ×lot)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if TSCH_WITH_LINK_SELECTOR
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_TSCH_SLOTFRAME, slotframe);
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_TSCH_TIMESLOT, timeslot);
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_callback_new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new)
|
||||
{
|
||||
/* Orchestra assumes that the time source is also the RPL parent.
|
||||
* This is the case if the following is set:
|
||||
* #define RPL_CALLBACK_PARENT_SWITCH tsch_rpl_callback_parent_switch
|
||||
* */
|
||||
|
||||
int i;
|
||||
if(new != old) {
|
||||
orchestra_parent_knows_us = 0;
|
||||
}
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->new_time_source != NULL) {
|
||||
all_rules[i]->new_time_source(old, new);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
orchestra_init(void)
|
||||
{
|
||||
int i;
|
||||
/* Snoop on packet transmission to know if our parent knows about us
|
||||
* (i.e. has ACKed at one of our DAOs since we decided to use it as a parent) */
|
||||
rime_sniffer_add(&orhcestra_sniffer);
|
||||
linkaddr_copy(&orchestra_parent_linkaddr, &linkaddr_null);
|
||||
/* Initialize all Orchestra rules */
|
||||
for(i = 0; i < NUM_RULES; i++) {
|
||||
if(all_rules[i]->init != NULL) {
|
||||
PRINTF("Orchestra: initializing rule %u\n", i);
|
||||
all_rules[i]->init(i);
|
||||
}
|
||||
}
|
||||
PRINTF("Orchestra: initialization done\n");
|
||||
}
|
74
apps/orchestra/orchestra.h
Normal file
74
apps/orchestra/orchestra.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Orchestra header file
|
||||
*
|
||||
* \author Simon Duquennoy <simonduq@sics.se>
|
||||
*/
|
||||
|
||||
#ifndef __ORCHESTRA_H__
|
||||
#define __ORCHESTRA_H__
|
||||
|
||||
#include "net/mac/tsch/tsch.h"
|
||||
#include "net/mac/tsch/tsch-conf.h"
|
||||
#include "net/mac/tsch/tsch-schedule.h"
|
||||
#include "orchestra-conf.h"
|
||||
|
||||
/* The structure of an Orchestra rule */
|
||||
struct orchestra_rule {
|
||||
void (* init)(uint16_t slotframe_handle);
|
||||
void (* new_time_source)(const struct tsch_neighbor *old, const struct tsch_neighbor *new);
|
||||
int (* select_packet)(uint16_t *slotframe, uint16_t *timeslot);
|
||||
void (* child_added)(const linkaddr_t *addr);
|
||||
void (* child_removed)(const linkaddr_t *addr);
|
||||
};
|
||||
|
||||
struct orchestra_rule eb_per_time_source;
|
||||
struct orchestra_rule unicast_per_neighbor;
|
||||
struct orchestra_rule default_common;
|
||||
|
||||
extern linkaddr_t orchestra_parent_linkaddr;
|
||||
extern int orchestra_parent_knows_us;
|
||||
|
||||
/* Call from application to start Orchestra */
|
||||
void orchestra_init(void);
|
||||
/* Callbacks requied for Orchestra to operate */
|
||||
/* Set with #define TSCH_CALLBACK_PACKET_READY orchestra_callback_packet_ready */
|
||||
void orchestra_callback_packet_ready(void);
|
||||
/* Set with #define TSCH_CALLBACK_NEW_TIME_SOURCE orchestra_callback_new_time_source */
|
||||
void orchestra_callback_new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new);
|
||||
/* Set with #define NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK orchestra_callback_child_added */
|
||||
void orchestra_callback_child_added(const linkaddr_t *addr);
|
||||
/* Set with #define NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK orchestra_callback_child_removed */
|
||||
void orchestra_callback_child_removed(const linkaddr_t *addr);
|
||||
|
||||
#endif /* __ORCHESTRA_H__ */
|
Loading…
Reference in a new issue