sixtop: 6top protocol implementation by CDAC

https://github.com/contiki-os/contiki/pull/1898
This commit is contained in:
Shalu-here 2016-10-21 16:23:08 +05:30 committed by Yasuyuki Tanaka
parent 69affad825
commit cc1c763db9
10 changed files with 1582 additions and 7 deletions

View File

@ -0,0 +1,23 @@
CONTIKI_PROJECT = node-sixtop
all: $(CONTIKI_PROJECT)
CONTIKI=../../..
CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\"
CONTIKI_WITH_IPV6 = 1
MAKE_WITH_ORCHESTRA ?= 0 # force Orchestra from command line
MAKE_WITH_SECURITY ?= 0 # force Security from command line
APPS += orchestra
MODULES += core/net/mac/tsch
MODULES += core/net/mac/tsch/sixtop
ifeq ($(MAKE_WITH_ORCHESTRA),1)
CFLAGS += -DWITH_ORCHESTRA=1
endif
ifeq ($(MAKE_WITH_SECURITY),1)
CFLAGS += -DWITH_SECURITY=1
endif
include $(CONTIKI)/Makefile.include

View File

@ -0,0 +1,39 @@
6top Example Description
------------------------
A RPL+TSCH node will act as basic node by default, but can be configured at startup
using the user button and following instructions from the log output. Every press
of a button toggles the mode as 6ln, 6dr or 6dr-sec (detailled next). After 10s with
no button press, the node starts in the last setting.
The modes are:
* 6ln (default): 6lowpan node, will join a RPL+TSCH network and act as router.
* 6dr: 6lowpan DAG Root, will start its own RPL+TSCH network. Note this is not a
border router, i.e. it does not have a serial interface with connection to
the Internet. For a border router, see ../border-router.
* 6dr-sec: 6lowpan DAG Root, starting a RPL+TSCH network with link-layer security
enabled. 6ln nodes are able to join both non-secured or secured networks.
6top Operation
---------------
If the mode is 6ln (node)
* The application triggers a 6P Add Request to 6dr (neighbor)
* Following this the application triggers another 6P Add Request to 6dr
* After an interval, the application triggers a 6P Delete Request to 6dr
For the Cooja simulation, you may use the rpl-tsch-sixtop-z1.csc file in this folder.
Once you run the simulation, "Mote output" window of Cooja simulator displays the
following messages.
For a 6P Add transaction,
ID:1 TSCH-sixtop: Sixtop IE received
ID:1 TSCH-sixtop: Send Link Response to node 2
ID:2 TSCH-sixtop: Sixtop IE received
ID:2 TSCH-sixtop: Schedule link x as RX with node 2
ID:2 TSCH-sixtop: Schedule link x as TX with node 1
Similarly for a 6P Delete transaction.

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* 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
* To test 6P transaction on a RPL+TSCH network
*
* \author
* Simon Duquennoy <simonduq@sics.se>
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
*/
#include "contiki.h"
#include "node-id.h"
#include "net/rpl/rpl.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/mac/tsch/tsch.h"
#include "net/rpl/rpl-private.h"
#include "net/ip/uip-debug.h"
#include "net/mac/tsch/sixtop/sixtop.h"
/*---------------------------------------------------------------------------*/
PROCESS(node_process, "RPL Node");
AUTOSTART_PROCESSES(&node_process);
/*---------------------------------------------------------------------------*/
static void
net_init(uip_ipaddr_t *br_prefix)
{
uip_ipaddr_t global_ipaddr;
if(br_prefix) { /* We are RPL root. Will be set automatically
as TSCH pan coordinator via the tsch-rpl module */
memcpy(&global_ipaddr, br_prefix, 16);
uip_ds6_set_addr_iid(&global_ipaddr, &uip_lladdr);
uip_ds6_addr_add(&global_ipaddr, 0, ADDR_AUTOCONF);
rpl_set_root(RPL_DEFAULT_INSTANCE, &global_ipaddr);
rpl_set_prefix(rpl_get_any_dag(), br_prefix, 64);
rpl_repair_root(RPL_DEFAULT_INSTANCE);
}
NETSTACK_MAC.on();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(node_process, ev, data)
{
static struct etimer et;
PROCESS_BEGIN();
/* 3 possible roles:
* - role_6ln: simple node, will join any network, secured or not
* - role_6dr: DAG root, will advertise (unsecured) beacons
* - role_6dr_sec: DAG root, will advertise secured beacons
* */
static int is_coordinator = 0, added_num_of_links = 0;
static enum { role_6ln, role_6dr, role_6dr_sec } node_role;
node_role = role_6ln;
/* Set node with MAC address c1:0c:00:00:00:00:01 as coordinator,
* convenient in cooja for regression tests using z1 nodes
* */
#ifdef CONTIKI_TARGET_Z1
extern unsigned char node_mac[8];
unsigned char coordinator_mac[8] = { 0xc1, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
if(memcmp(node_mac, coordinator_mac, 8) == 0) {
if(LLSEC802154_ENABLED) {
node_role = role_6dr_sec;
} else {
node_role = role_6dr;
}
} else {
node_role = role_6ln;
}
#endif
tsch_set_pan_secured(LLSEC802154_ENABLED && (node_role == role_6dr_sec));
is_coordinator = node_role > role_6ln;
if(is_coordinator) {
uip_ipaddr_t prefix;
uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
net_init(&prefix);
} else {
net_init(NULL);
}
etimer_set(&et, CLOCK_SECOND * 30);
while(1) {
PROCESS_YIELD_UNTIL(etimer_expired(&et));
etimer_reset(&et);
if(node_id != 1) {
clock_delay(1000);
if((added_num_of_links == 1) || (added_num_of_links == 3)) {
printf("App : Add a link\n");
sixtop_add_links((linkaddr_t *)0xffff, 1);
} else if(added_num_of_links == 5) {
printf("App : Delete a link\n");
sixtop_remove_link((linkaddr_t *)0xffff);
}
added_num_of_links++;
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2015, SICS Swedish ICT.
* 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.
*
*/
#ifndef __PROJECT_CONF_H__
#define __PROJECT_CONF_H__
/* Set to run orchestra */
#ifndef WITH_ORCHESTRA
#define WITH_ORCHESTRA 0
#endif /* WITH_ORCHESTRA */
/* Set to enable TSCH security */
#ifndef WITH_SECURITY
#define WITH_SECURITY 0
#endif /* WITH_SECURITY */
/*******************************************************/
/********* Enable RPL non-storing mode *****************/
/*******************************************************/
#undef UIP_CONF_MAX_ROUTES
#define UIP_CONF_MAX_ROUTES 0 /* No need for routes */
#undef RPL_CONF_MOP
#define RPL_CONF_MOP RPL_MOP_NON_STORING /* Mode of operation*/
#undef ORCHESTRA_CONF_RULES
#define ORCHESTRA_CONF_RULES { &eb_per_time_source, &unicast_per_neighbor_rpl_ns, &default_common } /* Orchestra in non-storing */
/*******************************************************/
/********************* Enable TSCH *********************/
/*******************************************************/
/* Netstack layers */
#undef NETSTACK_CONF_MAC
#define NETSTACK_CONF_MAC tschmac_driver
#undef NETSTACK_CONF_RDC
#define NETSTACK_CONF_RDC nordc_driver
#undef NETSTACK_CONF_FRAMER
#define NETSTACK_CONF_FRAMER framer_802154
/* IEEE802.15.4 frame version */
#undef FRAME802154_CONF_VERSION
#define FRAME802154_CONF_VERSION FRAME802154_IEEE802154E_2012
/* TSCH and RPL callbacks */
#define RPL_CALLBACK_PARENT_SWITCH tsch_rpl_callback_parent_switch
#define RPL_CALLBACK_NEW_DIO_INTERVAL tsch_rpl_callback_new_dio_interval
#define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network
#define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_network
/* Needed for CC2538 platforms only */
/* For TSCH we have to use the more accurate crystal oscillator
* by default the RC oscillator is activated */
#undef SYS_CTRL_CONF_OSC32K_USE_XTAL
#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1
/* Needed for cc2420 platforms only */
/* Disable DCO calibration (uses timerB) */
#undef DCOSYNCH_CONF_ENABLED
#define DCOSYNCH_CONF_ENABLED 0
/* Enable SFD timestamps (uses timerB) */
#undef CC2420_CONF_SFD_TIMESTAMPS
#define CC2420_CONF_SFD_TIMESTAMPS 1
/* Enable Sixtop Implementation */
#undef TSCH_CONF_WITH_SIXTOP
#define TSCH_CONF_WITH_SIXTOP 1
/*******************************************************/
/******************* Configure TSCH ********************/
/*******************************************************/
/* TSCH logging. 0: disabled. 1: basic log. 2: with delayed
* log messages from interrupt */
#undef TSCH_LOG_CONF_LEVEL
#define TSCH_LOG_CONF_LEVEL 2
/* IEEE802.15.4 PANID */
#undef IEEE802154_CONF_PANID
#define IEEE802154_CONF_PANID 0xabcd
/* Do not start TSCH at init, wait for NETSTACK_MAC.on() */
#undef TSCH_CONF_AUTOSTART
#define TSCH_CONF_AUTOSTART 0
/* 6TiSCH schedule length */
#undef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH
#define TSCH_SCHEDULE_CONF_DEFAULT_LENGTH 11
#if WITH_SECURITY
/* Enable security */
#undef LLSEC802154_CONF_ENABLED
#define LLSEC802154_CONF_ENABLED 1
/* TSCH uses explicit keys to identify k1 and k2 */
#undef LLSEC802154_CONF_USES_EXPLICIT_KEYS
#define LLSEC802154_CONF_USES_EXPLICIT_KEYS 1
/* TSCH uses the ASN rather than frame counter to construct the Nonce */
#undef LLSEC802154_CONF_USES_FRAME_COUNTER
#define LLSEC802154_CONF_USES_FRAME_COUNTER 0
#endif /* WITH_SECURITY */
#if WITH_ORCHESTRA
/* See apps/orchestra/README.md for more Orchestra configuration options */
#define TSCH_SCHEDULE_CONF_WITH_6TISCH_MINIMAL 0 /* No 6TiSCH minimal schedule */
#define TSCH_CONF_WITH_LINK_SELECTOR 1 /* Orchestra requires per-packet link selection */
/* Orchestra 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
#endif /* WITH_ORCHESTRA */
/*******************************************************/
/************* Other system configuration **************/
/*******************************************************/
#if CONTIKI_TARGET_Z1
/* Save some space to fit the limited RAM of the z1 */
#undef UIP_CONF_TCP
#define UIP_CONF_TCP 0
#undef QUEUEBUF_CONF_NUM
#define QUEUEBUF_CONF_NUM 2
#undef RPL_NS_CONF_LINK_NUM
#define RPL_NS_CONF_LINK_NUM 2
#undef NBR_TABLE_CONF_MAX_NEIGHBORS
#define NBR_TABLE_CONF_MAX_NEIGHBORS 2
#undef UIP_CONF_ND6_SEND_NA
#define UIP_CONF_ND6_SEND_NA 0
#undef SICSLOWPAN_CONF_FRAG
#define SICSLOWPAN_CONF_FRAG 0
#if WITH_SECURITY
/* Note: on sky or z1 in cooja, crypto operations are done in S/W and
* cannot be accommodated in normal slots. Use 65ms slots instead, and
* a very short 6TiSCH minimal schedule length */
#undef TSCH_CONF_DEFAULT_TIMESLOT_LENGTH
#define TSCH_CONF_DEFAULT_TIMESLOT_LENGTH 65000
#undef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH
#define TSCH_SCHEDULE_CONF_DEFAULT_LENGTH 2
/* Reduce log level to make space for security on z1 */
#undef TSCH_LOG_CONF_LEVEL
#define TSCH_LOG_CONF_LEVEL 0
#endif /* WITH_SECURITY */
#endif /* CONTIKI_TARGET_Z1 */
#if CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_ZOUL || \
CONTIKI_TARGET_OPENMOTE_CC2538
#define TSCH_CONF_HW_FRAME_FILTERING 0
#endif /* CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_ZOUL \
|| CONTIKI_TARGET_OPENMOTE_CC2538 */
#endif /* __PROJECT_CONF_H__ */

View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[APPS_DIR]/mrm</project>
<project EXPORT="discard">[APPS_DIR]/mspsim</project>
<project EXPORT="discard">[APPS_DIR]/avrora</project>
<project EXPORT="discard">[APPS_DIR]/serial_socket</project>
<project EXPORT="discard">[APPS_DIR]/collect-view</project>
<project EXPORT="discard">[APPS_DIR]/powertracker</project>
<simulation>
<title>My simulation</title>
<randomseed>123456</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>100.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
org.contikios.cooja.mspmote.Z1MoteType
<identifier>z11</identifier>
<description>Z1 Mote Type #z11</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/rpl-tsch-sixtop/node-sixtop.c</source>
<commands EXPORT="discard">make node-sixtop.z1 TARGET=z1</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/ipv6/rpl-tsch-sixtop/node-sixtop.z1</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDefaultSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>3.827476552301217</x>
<y>2.167129170680247</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspClock
<deviation>1.0</deviation>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>z11</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>30.278379737463556</x>
<y>17.799585117738026</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspClock
<deviation>1.0</deviation>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>2</id>
</interface_config>
<motetype_identifier>z11</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>280</width>
<z>0</z>
<height>160</height>
<location_x>400</location_x>
<location_y>0</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Visualizer
<plugin_config>
<moterelations>true</moterelations>
<skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
<viewport>4.027583163598053 0.0 0.0 4.027583163598053 133.5292942712438 14.03198741893021</viewport>
</plugin_config>
<width>400</width>
<z>3</z>
<height>160</height>
<location_x>1</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter>TSCH-sch</filter>
<formatted_time />
<coloring />
</plugin_config>
<width>854</width>
<z>1</z>
<height>342</height>
<location_x>0</location_x>
<location_y>161</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<mote>1</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<zoomfactor>500.0</zoomfactor>
</plugin_config>
<width>1366</width>
<z>5</z>
<height>166</height>
<location_x>0</location_x>
<location_y>503</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Notes
<plugin_config>
<notes>Enter notes here</notes>
<decorations>true</decorations>
</plugin_config>
<width>686</width>
<z>4</z>
<height>160</height>
<location_x>680</location_x>
<location_y>0</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.RadioLogger
<plugin_config>
<split>150</split>
<formatted_time />
<showdups>false</showdups>
<hidenodests>false</hidenodests>
</plugin_config>
<width>508</width>
<z>2</z>
<height>343</height>
<location_x>854</location_x>
<location_y>160</location_y>
</plugin>
</simconf>

View File

@ -0,0 +1,64 @@
# 6TiSCH Operation Sublayer (6top)
## **Overview**
6TiSCH Operation Sublayer (6top), a logical link layer in the 6TiSCH architecture, provides the abstraction of an IP link over a TSCH MAC layer (IEEE 802.15.4e). The functionality of 6top is to facilitate the dynamic cell negotiation with one-hop neighbors.
This is a Contiki implementation of 6top, which defines how to handle a 2-step 6top transaction on a basic RPL+TSCH network.
Developed by:
- Shalu R, CDAC, shalur@cdac.in, github user: [shalurajendran](https://github.com/shalurajendran)
- Lijo Thomas, CDAC, lijo@cdac.in
## **Features**
This implementation includes:
- 6top protocol(6P)
- 6P Add
- 6P Delete
- 2-step 6top Transaction
The code has been tested on Zolertia Z1 (z1, tested in cooja only) platform.
## **Code structure**
The 6top frame format is included in:
- core/net/mac/frame802154-ie.[ch]: Modified to include Sixtop Information Elements
6top is implemented in:
- core/net/mac/tsch/sixtop/sixtop.[ch]: 6top interface and 6top protocol(6P addition and deletion), handling of 6P Requests and Response
TSCH file modified:
- core/net/mac/tsch/tsch.[ch]: Modified to include Sixtop module
## **Using 6top**
A simple 6top+TSCH+RPL example is included under examples/ipv6/rpl-tsch-sixtop. Currently this application triggers the 6P transactions, later the 6top Scheduling Function (SF) may be implemented for the purpose.
To use 6top, make sure your platform supports TSCH and have sufficient memory.
To add 6top to your application, first include the Sixtop module in your Makefile with:
MODULES += core/net/mac/tsch/sixtop
Also enable the sixtop functionalities in your project-conf.h file with
#undef TSCH_CONF_WITH_SIXTOP
#define TSCH_CONF_WITH_SIXTOP 1
## **Additional documentation**
1. [IETF 6TiSCH Working Group](https://datatracker.ietf.org/wg/6tisch)
2. [6TiSCH 6top Protocol (6P)](https://tools.ietf.org/pdf/draft-ietf-6tisch-6top-protocol-02.pdf)

View File

@ -0,0 +1,839 @@
/*
* Copyright (c) 2016, Centre for Development of Advanced Computing (C-DAC).
* 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.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* IEEE 802.15.4 TSCH MAC Sixtop.
* \author
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
*/
#include <stdio.h>
#include "contiki.h"
#include "net/netstack.h"
#include "net/packetbuf.h"
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/tsch-packet.h"
#include "net/mac/tsch/tsch-private.h"
#include "net/mac/tsch/tsch-schedule.h"
#include "lib/random.h"
#include "sixtop.h"
#include "net/mac/frame802154e-ie.h"
#define DEBUG DEBUG_PRINT
#if DEBUG
#define PRINTF(...) printf(__VA_ARGS__)
#endif
#define WRITE16(buf, val) \
do { ((uint8_t *)(buf))[0] = (val) & 0xff; \
((uint8_t *)(buf))[1] = ((val) >> 8) & 0xff; \
} while(0);
#define READ16(buf, var) \
(var) = ((uint8_t *)(buf))[0] | ((uint8_t *)(buf))[1] << 8
/* Required number of links specified in Link Request IE */
uint8_t sixtop_request_num_links = 0;
/* Sequence Number of Link Request IE */
static int sixtop_request_seqno = 0;
/* Sequence Number of Link Response IE */
static int sixtop_response_seqno = 0;
/* Destination address of the last packet sent */
static linkaddr_t last_pkt_address;
/* IE information of the last packet sent */
struct ieee802154_ies last_pkt_ies;
/* SlotFrame ID specified in Link Request IE */
struct tsch_slotframe *req_sf;
/*---------------------------------------------------------------------------*/
/* Update the packet to be send with Sixtop Information Elements. Returns length of IE */
int
sixtop_update_ie(uint8_t *buf, struct ieee802154_ies *ies)
{
if(ies != NULL) {
uint8_t i = 0, code = 0, ie_len = 0, max = 0;
buf[2] = ies->ie_sixtop.subIE_id;
buf[3] = ies->ie_sixtop.version_code;
buf[4] = ies->ie_sixtop.schedule_fn_id;
/* 6P Code */
code = ies->ie_sixtop.version_code >> 4;
switch(code) {
case CMD_ADD:
case CMD_DELETE:
buf[5] = ies->ie_sixtop.num_links;
buf[6] = ies->ie_sixtop.frame_id;
if(code == CMD_ADD) {
max = SIXTOP_IE_MAX_LINKS;
} else { /* CMD_DELETE */
max = sixtop_request_num_links;
}
for(i = 0; i < max; i++) {
WRITE16(buf + 7 + i * 4, ies->ie_sixtop.linkList[i].timeslot);
WRITE16(buf + 7 + i * 4 + 2, ies->ie_sixtop.linkList[i].channel_offset);
}
ie_len = 5 + 4 * max;
break;
case RC_SUCCESS: /* Response Code Success */
for(i = 0; i < sixtop_request_num_links; i++) {
WRITE16(buf + 5 + i * 4, ies->ie_sixtop.linkList[i].timeslot);
WRITE16(buf + 5 + i * 4 + 2, ies->ie_sixtop.linkList[i].channel_offset);
}
ie_len = 3 + 4 * sixtop_request_num_links;
break;
default:
return -1;
}
return ie_len + 2; /* IE_len + IE_descriptor_len */
} else {
return -1;
}
}
/*---------------------------------------------------------------------------*/
/* Create a Sixtop IE for specified 6P code. Returns length of IEEE802.15.4e packet */
int
sixtop_create_ie(uint8_t *buf, linkaddr_t dest_addr, uint8_t code,
uint8_t sf_id, struct sixtop_link *sl)
{
uint8_t i = 0, len = 0, curr_len = 0, max = 0, sixtop_ie_offset = 0;
/* Schedule Function ID */
uint8_t schedule_fn_id = 0; /* SF0 */
struct ieee802154_ies ies;
/* IEEE 802.15.4 MAC Frame Header */
frame802154_t p;
memset(&p, 0, sizeof(p));
/* MAC Header : Frame Control Field */
p.fcf.frame_type = FRAME802154_DATAFRAME;
p.fcf.security_enabled = 0;
p.fcf.frame_pending = 0;
p.fcf.ack_required = 1;
p.fcf.panid_compression = 0;
p.fcf.sequence_number_suppression = FRAME802154_SUPPR_SEQNO;
p.fcf.ie_list_present = 1;
p.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE;
p.fcf.frame_version = FRAME802154_IEEE802154E_2012;
p.fcf.src_addr_mode = FRAME802154_LONGADDRMODE;
/* MAC Header : Sequence Number Field */
switch(code) {
case CMD_ADD:
case CMD_DELETE:
p.seq = sixtop_request_seqno;
sixtop_request_seqno++;
break;
case RC_SUCCESS: /* Response Code Success */
p.seq = sixtop_response_seqno;
break;
default:
break;
}
/* MAC Header : PAN ID and Address Fields */
p.dest_pid = frame802154_get_pan_id();
linkaddr_copy((linkaddr_t *)&p.dest_addr, &dest_addr);
p.src_pid = frame802154_get_pan_id();
linkaddr_copy((linkaddr_t *)&p.src_addr, &linkaddr_node_addr);
/* MAC Header : Auxillary Security Header */
#if TSCH_SECURITY_ENABLED
if(tsch_is_pan_secured) {
p.fcf.security_enabled = 1;
p.aux_hdr.security_control.security_level = TSCH_SECURITY_KEY_SEC_LEVEL_ACK;
p.aux_hdr.security_control.key_id_mode = FRAME802154_1_BYTE_KEY_ID_MODE;
p.aux_hdr.security_control.frame_counter_suppression = 1;
p.aux_hdr.security_control.frame_counter_size = 1;
p.aux_hdr.key_index = TSCH_SECURITY_KEY_INDEX_ACK;
}
#endif /* TSCH_SECURITY_ENABLED */
/* Copy MAC Header to Buffer */
if((curr_len = frame802154_create(&p, buf)) == 0) {
return 0;
}
memset(&ies, 0, sizeof(ies));
/* Header IE Termination 1 */
/* First add header-IE termination IE to stipulate that next come payload IEs */
if((len = frame80215e_create_ie_header_list_termination_1(buf + curr_len, PACKETBUF_SIZE - curr_len, &ies)) == -1) {
return -1;
}
curr_len += len;
/* Save offset of the Sixtop IE descriptor, we need to know the total length
* before writing it */
sixtop_ie_offset = curr_len;
/* Update Sixtop Information Elements */
ies.ie_sixtop.subIE_id = SIXTOP_SUBIE_ID;
ies.ie_sixtop.version_code = (code << 4) | SIXTOP_VERSION;
ies.ie_sixtop.schedule_fn_id = schedule_fn_id;
switch(code) {
case CMD_ADD:
case CMD_DELETE:
if(code == CMD_ADD) {
max = SIXTOP_IE_MAX_LINKS;
} else {
max = 1;
}
ies.ie_sixtop.frame_id = sf_id;
ies.ie_sixtop.num_links = sixtop_request_num_links;
for(i = 0; i < max; i++) {
if(sl[i].link_option != LINK_OPTION_OFF) {
ies.ie_sixtop.linkList[i].timeslot = sl[i].timeslot;
ies.ie_sixtop.linkList[i].channel_offset = sl[i].channel_offset;
}
}
break;
case RC_SUCCESS: /* Response Code Success */
for(i = 0; i < sixtop_request_num_links; i++) {
ies.ie_sixtop.linkList[i].timeslot = sl[i].timeslot;
ies.ie_sixtop.linkList[i].channel_offset = sl[i].channel_offset;
}
break;
default:
break;
}
/* Save a copy of Sixtop IE */
last_pkt_ies = ies;
/* Copy Sixtop IE content to buffer */
if((len = sixtop_update_ie(buf + curr_len, &ies)) == -1) {
return -1;
}
curr_len += len;
/* Outer IE descriptor - Sixtop */
ies.ie_mlme_len = curr_len - sixtop_ie_offset - 2;
if((len = frame80215e_create_ie_sixtop(buf + sixtop_ie_offset, PACKETBUF_SIZE - sixtop_ie_offset, &ies)) == -1) {
return -1;
}
return curr_len;
}
/*---------------------------------------------------------------------------*/
/* Fetch the CandidateLinkList for Addition. Returns 0 if success */
int
sixtop_get_link_list_for_addition(uint8_t sf_id, struct sixtop_link *sl)
{
uint8_t i = 0, index = 0;
/* Flag to prevent repeated slots */
uint8_t slot_check = 1;
uint16_t random_slot = 0;
struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(sf_id);
do {
/* Randomly select a slot offset within TSCH_SCHEDULE_DEFAULT_LENGTH */
random_slot = ((random_rand() & 0xFF)) % TSCH_SCHEDULE_DEFAULT_LENGTH;
if(!tsch_schedule_get_link_by_timeslot(sf, random_slot)) { /* NULL value indicates a free link */
/* To prevent repeated slots */
for(i = 0; i < index; i++) {
if(!(sl[i].timeslot == random_slot)) {
/* Random selection resulted in a free slot */
if(i == index - 1) { /* Checked till last index of link list */
slot_check = 1;
break;
}
} else {
/* Slot already present in CandidateLinkList */
slot_check++;
break;
}
}
/* Random selection resulted in a free slot, add it to linklist */
if(slot_check == 1) {
sl[index].timeslot = random_slot;
sl[index].channel_offset = 0;
sl[index].link_option = LINK_OPTION_TX;
index++;
slot_check++;
} else if(slot_check > TSCH_SCHEDULE_DEFAULT_LENGTH) {
PRINTF("TSCH-sixtop:! Number of trials for free slot exceeded...\n");
return -1;
break; /* exit while loop */
}
}
} while(index < SIXTOP_IE_MAX_LINKS);
if(index == 0) {
return -1;
} else {
return 0;
}
}
/*---------------------------------------------------------------------------*/
/* Fetches the CandidateLinkList (atmost one link) for Deletion. Returns 0 if success */
int
sixtop_get_link_list_for_deletion(uint8_t sf_id, struct sixtop_link *sl, linkaddr_t *dest_addr)
{
uint8_t i = 0, index = 0;
struct tsch_link *l;
struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(sf_id);
for(i = 0; i < TSCH_SCHEDULE_DEFAULT_LENGTH; i++) {
l = tsch_schedule_get_link_by_timeslot(sf, i);
if(l) {
/* Non-zero value indicates a scheduled link */
if((linkaddr_cmp(&l->addr, dest_addr)) && (l->link_options == LINK_OPTION_TX)) {
/* This link is scheduled as a TX link to the specified neighbor */
sl[index].timeslot = i;
sl[index].channel_offset = l->channel_offset;
sl[index].link_option = LINK_OPTION_TX;
index++;
break; /* delete atmost one */
}
}
}
if(index == 0) {
return -1;
} else {
return 0;
}
}
/*---------------------------------------------------------------------------*/
/* Adds links to the schedule as Tx/Rx depending on the sixtop_state value */
void
sixtop_add_links_to_schedule(uint8_t sf_id, struct sixtop_link *sl,
linkaddr_t *previous_hop, uint8_t state)
{
uint8_t i = 0, num_added_links = 0;
for(i = 0; i < SIXTOP_IE_MAX_LINKS; i++) {
if(sl[i].timeslot != 0xFFFF) {
switch(state) {
case SIXTOP_ADD_RESPONSE_WAIT_SENDDONE:
PRINTF("TSCH-sixtop: Schedule link %d as RX with node %u\n", sl[i].timeslot, previous_hop->u8[7]);
/* Add a TX link to neighbor */
tsch_schedule_add_link(tsch_schedule_get_slotframe_by_handle(sf_id),
LINK_OPTION_RX, LINK_TYPE_NORMAL, previous_hop,
sl[i].timeslot, sl[i].channel_offset);
break;
case SIXTOP_ADD_RESPONSE_RECEIVED:
PRINTF("TSCH-sixtop: Schedule link %d as TX with node %u\n", sl[i].timeslot, previous_hop->u8[7]);
/* Add a RX link to neighbor */
tsch_schedule_add_link(tsch_schedule_get_slotframe_by_handle(sf_id),
LINK_OPTION_TX, LINK_TYPE_NORMAL, previous_hop,
sl[i].timeslot, sl[i].channel_offset);
break;
default:
PRINTF("TSCH-sixtop:! Sixtop_state error\n");
break;
}
num_added_links++;
if(num_added_links == sixtop_request_num_links) {
break;
}
}
}
}
/*---------------------------------------------------------------------------*/
/* Remove links from schedule */
void
sixtop_remove_links_from_schedule(uint8_t sf_id, struct sixtop_link *sl,
linkaddr_t *previous_hop)
{
uint8_t i = 0;
struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(sf_id);
for(i = 0; i < sixtop_request_num_links; i++) {
PRINTF("TSCH-sixtop: Remove link %d from the schedule\n", sl[i].timeslot);
tsch_schedule_remove_link_by_timeslot(sf, sl[i].timeslot);
}
}
/*---------------------------------------------------------------------------*/
/* Process the callback of a Sixtop IE by sixtop_state */
void
sixtop_ie_process_callback(struct ieee802154_ies *ies, linkaddr_t *dest_addr)
{
uint8_t i = 0, frame_id = 0;
struct sixtop_link sl[SIXTOP_IE_MAX_LINKS];
switch(sixtop_state) {
case SIXTOP_ADD_REQUEST_WAIT_SENDDONE:
sixtop_state = SIXTOP_ADD_RESPONSE_WAIT;
break;
case SIXTOP_DELETE_REQUEST_WAIT_SENDDONE:
sixtop_state = SIXTOP_DELETE_RESPONSE_WAIT;
break;
case SIXTOP_ADD_RESPONSE_WAIT_SENDDONE:
case SIXTOP_DELETE_RESPONSE_WAIT_SENDDONE:
frame_id = ies->ie_sixtop.frame_id;
if(sixtop_request_num_links > 0) {
for(i = 0; i < sixtop_request_num_links; i++) {
sl[i].timeslot = ies->ie_sixtop.linkList[i].timeslot;
sl[i].channel_offset = ies->ie_sixtop.linkList[i].channel_offset;
}
if(sixtop_state == SIXTOP_ADD_RESPONSE_WAIT_SENDDONE) {
/* Add links to TSCH schedule */
sixtop_add_links_to_schedule(frame_id, sl, dest_addr, sixtop_state);
} else { /* SIXTOP_DELETE_RESPONSE_WAIT_SENDDONE */
/* Remove links from TSCH schedule */
sixtop_remove_links_from_schedule(frame_id, sl, dest_addr);
}
}
break;
default:
/* log error */
break;
}
}
/*---------------------------------------------------------------------------*/
/* Tx callback for Sixtop IE */
static void
sixtop_packet_sent(void *ptr, int status, int transmissions)
{
/*PRINTF("TSCH-sixtop: Sixtop IE sent to %u, st %d-%d\n",
last_pkt_address.u8[7], status, transmissions);*/
/* Process the callback by sixtop_state */
sixtop_ie_process_callback(&last_pkt_ies, &last_pkt_address);
}
/*---------------------------------------------------------------------------*/
/* Initiates transmission of a Link Request */
int
sixtop_create_link_request(uint8_t code, linkaddr_t *dest_addr, uint16_t num_Links)
{
uint8_t len = 0;
struct sixtop_link sl[SIXTOP_IE_MAX_LINKS];
/* Get time-source neighbor */
struct tsch_neighbor *n = tsch_queue_get_time_source();
req_sf = tsch_schedule_get_slotframe_by_handle(0); /* Slotframe 0 */
memset(sl, 0, sizeof(sl));
if(dest_addr == NULL) {
return -1;
}
sixtop_request_num_links = num_Links;
if(code == CMD_ADD) {
/* Fetch CandidateLinkList for addition */
if(sixtop_get_link_list_for_addition(req_sf->handle, sl) == -1) {
return -1;
}
} else if(code == CMD_DELETE) {
/* Fetch CandidateLinkList for deletion */
if(sixtop_get_link_list_for_deletion(req_sf->handle, sl, &n->addr) == -1) {
return -1;
}
}
if(tsch_queue_packet_count(&n->addr) == 0) {
/* Get a free buffer */
packetbuf_clear();
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, SIXTOP_CONF_MAX_MAC_TRANSMISSIONS);
/* Save destination address of last packet sent */
last_pkt_address = n->addr;
/* Create IE by 6P code */
len += sixtop_create_ie(packetbuf_dataptr(), n->addr, code, req_sf->handle, sl);
if(len != 0) {
struct tsch_packet *p;
packetbuf_set_datalen(len);
/* Add packet to Tx queue. TSCH layer schedules transmission */
if(!(p = tsch_queue_add_packet(&n->addr, sixtop_packet_sent, NULL))) {
PRINTF("TSCH-sixtop:! could not enqueue 6top packet\n");
}
} else {
return -1;
}
}
if(code == CMD_ADD) {
sixtop_state = SIXTOP_ADD_REQUEST_WAIT_SENDDONE;
} else if(code == CMD_DELETE) {
sixtop_state = SIXTOP_DELETE_REQUEST_WAIT_SENDDONE;
}
return 0;
}
/*---------------------------------------------------------------------------*/
/* Initiates transmission of a Link Response (On receiving a Link Request) */
void
sixtop_create_link_response(uint8_t code, linkaddr_t *dest_addr, struct ieee802154_ies *ies)
{
uint8_t i = 0, len = 0, frame_id = 0;
struct sixtop_link sl[SIXTOP_IE_MAX_LINKS];
/* Save destination address of last packet sent */
linkaddr_copy((linkaddr_t *)&last_pkt_address, dest_addr);
frame_id = ies->ie_sixtop.frame_id;
for(i = 0; i < SIXTOP_IE_MAX_LINKS; i++) {
sl[i].timeslot = ies->ie_sixtop.linkList[i].timeslot;
sl[i].channel_offset = ies->ie_sixtop.linkList[i].channel_offset;
}
if(tsch_queue_packet_count(&last_pkt_address) == 0) {
/* Get a free buffer */
packetbuf_clear();
packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, SIXTOP_CONF_MAX_MAC_TRANSMISSIONS);
/* Create a Sixtop Link Response packet */
len += sixtop_create_ie(packetbuf_dataptr(), last_pkt_address, RC_SUCCESS, frame_id, sl);
if(len != 0) {
struct tsch_packet *p;
packetbuf_set_datalen(len);
last_pkt_ies = *ies;
/* Add packet to Tx queue. TSCH layer schedules transmission */
if(!(p = tsch_queue_add_packet(&last_pkt_address, sixtop_packet_sent, NULL))) {
PRINTF("TSCH-sixtop:! could not enqueue 6top packet\n");
}
}
if(code == CMD_ADD) {
sixtop_state = SIXTOP_ADD_RESPONSE_WAIT_SENDDONE;
} else if(code == CMD_DELETE) {
sixtop_state = SIXTOP_DELETE_RESPONSE_WAIT_SENDDONE;
}
}
}
/*---------------------------------------------------------------------------*/
/* Initiates a Sixtop Link addition
* Neighbor can be specified from application or upper layers
* Currently Time source neighbor is taken as default
* Returns 0 if Success
*/
int
sixtop_add_links(linkaddr_t *dest_addr, uint8_t num_Links)
{
/* Create a Sixtop Add Request. Return 0 if Success */
if(sixtop_create_link_request(CMD_ADD, dest_addr, num_Links) == -1) {
PRINTF("TSCH-sixtop:! Add link failed");
return -1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
/* Initiates a Sixtop Link deletion
* Neighbor can be specified from application or upper layers
* Currently Time source neighbor is taken as default
* Returns 0 if Success
*/
int
sixtop_remove_link(linkaddr_t *dest_addr)
{
/* Create a Sixtop Delete Request. Return 0 if Success */
if(sixtop_create_link_request(CMD_DELETE, dest_addr, 1) == -1) { /* delete atmost one */
PRINTF("TSCH-sixtop:! Delete link failed");
return -1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
/* Check links for addition/deletion. Returns 0 if feasible */
int
sixtop_are_links_feasible(uint8_t code, uint8_t frame_id, struct sixtop_link *sl)
{
uint8_t i = 0;
/* Counter for infeasible number of links
* A non-zero value indicates infeasibility */
uint8_t infeasible_num_links = sixtop_request_num_links;
if(sixtop_request_num_links > SIXTOP_IE_MAX_LINKS) {
return -1;
} else {
if(code == CMD_ADD) {
do {
/* Checking availability of requested number of slots */
if(tsch_schedule_get_link_by_timeslot(tsch_schedule_get_slotframe_by_handle(0), sl[i].timeslot) == NULL) {
/* A free link present */
infeasible_num_links--;
} else {
sl[i].timeslot = 0xFFFF; /* Error */
}
i++;
} while(i < sixtop_request_num_links && infeasible_num_links > 0);
} else if(code == CMD_DELETE) {
do {
/* Ensure before delete */
if(tsch_schedule_get_link_by_timeslot(tsch_schedule_get_slotframe_by_handle(0), sl[i].timeslot)) {
/* A scheduled link present */
infeasible_num_links--;
} else {
sl[i].timeslot = 0xFFFF; /* Error */
}
i++;
} while(i < sixtop_request_num_links && infeasible_num_links > 0);
}
if(infeasible_num_links == 0) { /* Links are feasible */
while(i < sixtop_request_num_links) {
sl[i].timeslot = 0xFFFF; /* Error */
i++;
}
return 0; /* Return success(0) */
}
}
return -1;
}
/*---------------------------------------------------------------------------*/
/* Process Sixtop IE by code */
void
sixtop_process_by_code(uint8_t code, struct ieee802154_ies *ies, linkaddr_t *dest_addr)
{
uint8_t frame_id = 0, i = 0;
struct sixtop_link sl[SIXTOP_IE_MAX_LINKS];
switch(code) {
case CMD_ADD:
case CMD_DELETE:
frame_id = ies->ie_sixtop.frame_id;
/* Are the links feasible for addition/deletion. Returns 0 if feasible */
if(!(sixtop_are_links_feasible(code, frame_id, ies->ie_sixtop.linkList))) {
PRINTF("TSCH-sixtop: Send Link Response to node %d\n", dest_addr->u8[7]);
/* Links are feasible. Create Link Response packet */
sixtop_create_link_response(code, dest_addr, ies);
}
break;
case RC_SUCCESS: /* Response Code Success */
frame_id = req_sf->handle;
for(i = 0; i < sixtop_request_num_links; i++) {
sl[i].timeslot = ies->ie_sixtop.linkList[i].timeslot;
sl[i].channel_offset = ies->ie_sixtop.linkList[i].channel_offset;
}
/* Add/delete links to/from Schedule */
if(sixtop_state == SIXTOP_ADD_RESPONSE_RECEIVED) {
sixtop_add_links_to_schedule(frame_id, sl, dest_addr, sixtop_state);
} else if(sixtop_state == SIXTOP_DELETE_RESPONSE_RECEIVED) {
sixtop_remove_links_from_schedule(frame_id, sl, dest_addr);
}
break;
default:
break;
}
}
/*---------------------------------------------------------------------------*/
/* Parse a Sixtop IE. Returns length of IE */
int
sixtop_parse_ie(const uint8_t *buf, linkaddr_t *dest_addr)
{
struct ieee802154_ies ies;
uint8_t i = 0, max = 0, ie_len = 0;
/* Parse the 6top message elements */
int subIE_id = buf[4];
int version_code = buf[5];
/* Parse the 6P Code */
int code = (version_code & 0xF0) >> 4;
/* Check for 6P SubIE and 6P Version */
if(subIE_id == SIXTOP_SUBIE_ID && (version_code & SIXTOP_VERSION)) {
ies.ie_sixtop.subIE_id = buf[4];
ies.ie_sixtop.version_code = buf[5];
ies.ie_sixtop.schedule_fn_id = buf[6];
switch(code) {
case CMD_ADD:
case CMD_DELETE:
ies.ie_sixtop.num_links = buf[7];
ies.ie_sixtop.frame_id = buf[8];
/* Save the number of links specified in Link Request IE */
sixtop_request_num_links = ies.ie_sixtop.num_links;
if(sixtop_request_num_links == 0) {
PRINTF("TSCH-sixtop:! Requested number of links is zero\n");
return -1;
}
if(code == CMD_ADD) {
max = SIXTOP_IE_MAX_LINKS;
PRINTF("TSCH-sixtop: Received a 6P Add Request for %d links from node %d with LinkList : ",
sixtop_request_num_links, dest_addr->u8[7]);
} else { /* CMD_DELETE */
max = ies.ie_sixtop.num_links; /* delete atmost one */
PRINTF("TSCH-sixtop: Received a 6P Delete Request for %d links from node %d with LinkList : ",
sixtop_request_num_links, dest_addr->u8[7]);
}
/* Parse the Candidate Link List */
for(i = 0; i < max; i++) {
READ16(buf + 9 + i * 4, ies.ie_sixtop.linkList[i].timeslot);
READ16(buf + 9 + i * 4 + 2, ies.ie_sixtop.linkList[i].channel_offset);
PRINTF("%d ", ies.ie_sixtop.linkList[i].timeslot);
}
PRINTF("\n");
/* Update the IE length */
ie_len = 9 + (max * 4);
/* Process Sixtop IE by code */
sixtop_process_by_code(code, &ies, dest_addr);
break;
case RC_SUCCESS: /* Response Code Success */
if(sixtop_state == SIXTOP_ADD_RESPONSE_WAIT) {
PRINTF("TSCH-sixtop: Received a 6P Add Response from node %d with LinkList : ", dest_addr->u8[7]);
sixtop_state = SIXTOP_ADD_RESPONSE_RECEIVED;
} else if(sixtop_state == SIXTOP_DELETE_RESPONSE_WAIT) {
PRINTF("TSCH-sixtop: Received a 6P Delete Response from node %d with LinkList : ", dest_addr->u8[7]);
sixtop_state = SIXTOP_DELETE_RESPONSE_RECEIVED;
}
/* Parse the Candidate Link List */
for(i = 0; i < sixtop_request_num_links; i++) {
READ16(buf + 7 + i * 4, ies.ie_sixtop.linkList[i].timeslot);
READ16(buf + 7 + i * 4 + 2, ies.ie_sixtop.linkList[i].channel_offset);
PRINTF("%d ", ies.ie_sixtop.linkList[i].timeslot);
}
PRINTF("\n");
/* Update the IE length */
ie_len = 7 + (sixtop_request_num_links * 4);
/* Process Sixtop IE by code */
sixtop_process_by_code(code, &ies, dest_addr);
break;
default:
break;
}
}
return ie_len;
}
/*---------------------------------------------------------------------------*/
/* Is it a Sixtop IE? Returns 0 if success */
int
sixtop_is_sixtop_ie(const uint8_t *buf, int buf_size,
frame802154_t *frame, struct ieee802154_ies *ies)
{
uint8_t curr_len = 0;
int ret;
if(frame == NULL || buf_size < 0) {
return -1;
}
/* Parse 802.15.4-2006 frame, i.e. all fields before Information Elements */
if((ret = frame802154_parse((uint8_t *)buf, buf_size, frame)) == 0) {
PRINTF("TSCH-sixtop:! parse_sixtop_ie: failed to parse frame\n");
return -1;
}
if(frame->fcf.frame_version < FRAME802154_IEEE802154E_2012
|| frame->fcf.frame_type != FRAME802154_DATAFRAME) {
PRINTF("TSCH-sixtop:! parse_sixtop_ie: frame is not a valid Sixtop IE. Frame version %u, type %u, FCF %02x %02x\n",
frame->fcf.frame_version, frame->fcf.frame_type, buf[0], buf[1]);
PRINTF("TSCH-sixtop:! parse_sixtop_ie: frame was from 0x%x/", frame->src_pid);
PRINTLLADDR((const uip_lladdr_t *)&frame->src_addr);
PRINTF(" to 0x%x/", frame->dest_pid);
PRINTLLADDR((const uip_lladdr_t *)&frame->dest_addr);
PRINTF("\n");
return -1;
}
curr_len += ret;
if(ies != NULL) {
memset(ies, 0, sizeof(struct ieee802154_ies));
}
if(frame->fcf.ie_list_present) {
int mic_len = 0;
/* Parse information elements. We need to substract the MIC length, as the exact payload len is needed while parsing */
if((ret = frame802154e_parse_information_elements(buf + curr_len, buf_size - curr_len - mic_len, ies)) == -1) {
PRINTF("TSCH-sixtop:! parse_sixtop_ie: failed to parse IEs\n");
return -1;
} else if(!ret) {
PRINTF("TSCH-sixtop: Sixtop IE received\n");
return 0; /* Sixtop IE found. Return success(0) */
}
curr_len += ret;
}
return curr_len;
}
/*---------------------------------------------------------------------------*/
/* Set the Sequence Number of Link Response as in Link Request */
/* Function is called from TSCH layer on receiving a Sixtop IE */
void
sixtop_set_seqno(uint8_t seq_num)
{
sixtop_response_seqno = seq_num;
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2007, 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.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* A sixtop protocol that performs link addition/deletion
* \author
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
*/
#ifndef __SIXTOP_H__
#define __SIXTOP_H__
#include "contiki.h"
#include "stdbool.h"
#include "net/ip/uip-debug.h"
#include "net/linkaddr.h"
#include "net/netstack.h"
#include "net/mac/tsch/tsch-schedule.h"
#include "net/mac/tsch/tsch-asn.h"
#define SIXTOP_SUBIE_ID 0x00
#define SIXTOP_VERSION 0x01
/* Link Option OFF */
#define LINK_OPTION_OFF 0
/* Maximum number of retransmissions permissible at MAC layer */
#define SIXTOP_CONF_MAX_MAC_TRANSMISSIONS 3
/* 6P Command ID */
enum sixtop_command_id {
CMD_ADD = 0x01,
CMD_DELETE = 0x02,
CMD_COUNT = 0x03,
CMD_LIST = 0x04,
CMD_CLEAR = 0x05,
};
/* 6P Return Code */
enum sixtop_return_code {
RC_SUCCESS = 0x06, /* Operation succeeded */
RC_VER_ERR = 0x07, /* Unsupported 6P version */
RC_SFID_ERR = 0x08, /* Unsupported SFID */
RC_BUSY = 0x09, /* Handling previous request */
RC_RESET = 0x0a, /* Abort 6P transaction */
RC_ERR = 0x0b, /* Operation failed */
};
/* Sixtop State Machine */
enum {
SIXTOP_IDLE = 0x00,
SIXTOP_ADD_REQUEST_WAIT_SENDDONE = 0x01, /* Waiting for SendDone confirmation of Add Request */
SIXTOP_ADD_RESPONSE_WAIT = 0x02, /* Waiting for Add Response */
SIXTOP_ADD_RESPONSE_WAIT_SENDDONE = 0x03, /* Waiting for SendDone confirmation of Add Response */
SIXTOP_ADD_RESPONSE_RECEIVED = 0x04, /* Received Add Response */
SIXTOP_DELETE_REQUEST_WAIT_SENDDONE = 0x05, /* Waiting for SendDone confirmation of Delete Request */
SIXTOP_DELETE_RESPONSE_WAIT = 0x06, /* waiting for Delete Response */
SIXTOP_DELETE_RESPONSE_WAIT_SENDDONE = 0x07, /* Waiting for SendDone confirmation of Add Response */
SIXTOP_DELETE_RESPONSE_RECEIVED = 0x08, /* Received Delete Response */
} sixtop_state;
/********** Functions *********/
/* Initiates a Sixtop Link addition */
int sixtop_add_links(linkaddr_t *dest_addr, uint8_t num_Links);
/* Initiates a Sixtop Link deletion */
int sixtop_remove_link(linkaddr_t *dest_addr);
/* Is it a Sixtop IE? Returns 0 if success */
int sixtop_is_sixtop_ie(const uint8_t *buf, int buf_size, frame802154_t *frame, struct ieee802154_ies *ies);
/* Set the Sequence Number of Link Response as in Link Request */
void sixtop_set_seqno(uint8_t seq_num);
/* Parse a Sixtop IE. Returns length of IE */
int sixtop_parse_ie(const uint8_t *buf, linkaddr_t *dest_addr);
#endif /* __SIXTOP_H__ */

View File

@ -55,6 +55,7 @@
#include "net/mac/tsch/tsch-log.h"
#include "net/mac/tsch/tsch-packet.h"
#include "net/mac/tsch/tsch-security.h"
#include "net/mac/tsch/sixtop/sixtop.h"
#include "net/mac/mac-sequence.h"
#include "lib/random.h"
@ -245,7 +246,6 @@ tsch_reset(void)
#endif /* TSCH_AUTOSELECT_TIME_SOURCE */
tsch_set_eb_period(TSCH_EB_PERIOD);
}
/* TSCH keep-alive functions */
/*---------------------------------------------------------------------------*/
@ -407,7 +407,6 @@ eb_input(struct input_packet *current_input)
}
}
}
/*---------------------------------------------------------------------------*/
/* Process pending input packet(s) */
static void
@ -424,6 +423,28 @@ tsch_rx_process_pending()
&& frame.fcf.frame_version == FRAME802154_IEEE802154_2015
&& frame.fcf.frame_type == FRAME802154_BEACONFRAME;
#if TSCH_WITH_SIXTOP
int is_ie = ret
&& frame.fcf.frame_version == FRAME802154_IEEE802154E_2012
&& frame.fcf.frame_type == FRAME802154_DATAFRAME
&& frame.fcf.ie_list_present == 1;
if(is_ie) {
/* IE received (Data may/ maynot be present) */
/* Save sequence number of Link Request */
sixtop_set_seqno(frame.seq);
/* Check and parse, if it is a Sixtop IE. Returns length of data */
uint8_t data_len = ie_input(current_input);
if(data_len <= 0) {
/* Only Sixtop IE present , no data */
is_data = 0;
}
}
#endif /* TSCH_WITH_SIXTOP */
if(is_data) {
/* Skip EBs and other control messages */
/* Copy to packetbuf for processing */
@ -443,7 +464,6 @@ tsch_rx_process_pending()
ringbufindex_get(&input_ringbuf);
}
}
/*---------------------------------------------------------------------------*/
/* Pass sent packets to upper layer */
static void
@ -613,9 +633,9 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
ies.ie_tsch_slotframe_and_link.slotframe_size);
for(i = 0; i < num_links; i++) {
tsch_schedule_add_link(sf,
ies.ie_tsch_slotframe_and_link.links[i].link_options,
LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
ies.ie_tsch_slotframe_and_link.links[i].timeslot, ies.ie_tsch_slotframe_and_link.links[i].channel_offset);
ies.ie_tsch_slotframe_and_link.links[i].link_options,
LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
ies.ie_tsch_slotframe_and_link.links[i].timeslot, ies.ie_tsch_slotframe_and_link.links[i].channel_offset);
}
} else {
LOG_ERR("! parse_eb: too many links in schedule (%u)\n", num_links);
@ -672,7 +692,6 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
LOG_ERR("! did not associate.\n");
return 0;
}
/* Processes and protothreads used by TSCH */
/*---------------------------------------------------------------------------*/

View File

@ -145,6 +145,13 @@
#define TSCH_AUTOSELECT_TIME_SOURCE 0
#endif /* TSCH_CONF_EB_AUTOSELECT */
/* To include Sixtop Implementation */
#ifdef TSCH_CONF_WITH_SIXTOP
#define TSCH_WITH_SIXTOP TSCH_CONF_WITH_SIXTOP
#else
#define TSCH_WITH_SIXTOP 0
#endif /* TSCH_CONF_EB_AUTOSELECT */
/*********** Callbacks *********/
/* Called by TSCH when joining a network */