sixtop: refactoring

- support draft-ietf-6tisch-6top-protocol-03
- maintain a sequence number per neighbor
- rename variables and constants
- reconsider file structure and file names
- make sf-simple part of example
- update sixtop/README.md
- add regression-tests for 6tisch
- apply C-DAC copyright notice
- bugfix + cleanup
This commit is contained in:
Yasuyuki Tanaka 2016-11-02 14:12:07 +01:00 committed by Yasuyuki Tanaka
parent cc1c763db9
commit a5fadb2ebe
40 changed files with 9727 additions and 953 deletions

View File

@ -104,3 +104,4 @@ env:
- BUILD_TYPE='ipv6' BUILD_CATEGORY='sim'
- BUILD_TYPE='base' BUILD_CATEGORY='sim'
- BUILD_TYPE='ieee802154' BUILD_CATEGORY='sim'
- BUILD_TYPE='6tisch' BUILD_CATEGORY='sim'

View File

@ -1,20 +1,15 @@
CONTIKI_PROJECT = node-sixtop
all: $(CONTIKI_PROJECT)
PROJECT_SOURCEFILES += sf-simple.c
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
MODULES += os/net/mac/tsch
MODULES += os/net/mac/tsch/sixtop
ifeq ($(MAKE_WITH_SECURITY),1)
CFLAGS += -DWITH_SECURITY=1

View File

@ -33,7 +33,7 @@
*
* \author
* Simon Duquennoy <simonduq@sics.se>
* Shalu R <shalur@cdac.in>
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
*/
@ -42,9 +42,12 @@
#include "net/rpl/rpl.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/tsch-schedule.h"
#include "net/mac/tsch/sixtop/sixtop.h"
#include "net/rpl/rpl-private.h"
#include "net/ip/uip-debug.h"
#include "net/mac/tsch/sixtop/sixtop.h"
#include "sf-simple.h"
/*---------------------------------------------------------------------------*/
PROCESS(node_process, "RPL Node");
@ -72,6 +75,8 @@ net_init(uip_ipaddr_t *br_prefix)
PROCESS_THREAD(node_process, ev, data)
{
static struct etimer et;
struct tsch_neighbor *n;
PROCESS_BEGIN();
/* 3 possible roles:
@ -104,6 +109,7 @@ PROCESS_THREAD(node_process, ev, data)
tsch_set_pan_secured(LLSEC802154_ENABLED && (node_role == role_6dr_sec));
is_coordinator = node_role > role_6ln;
sixtop_add_sf(&sf_simple_driver);
if(is_coordinator) {
uip_ipaddr_t prefix;
@ -118,14 +124,17 @@ PROCESS_THREAD(node_process, ev, data)
PROCESS_YIELD_UNTIL(etimer_expired(&et));
etimer_reset(&et);
/* Get time-source neighbor */
n = tsch_queue_get_time_source();
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);
sf_simple_add_links(&n->addr, 1);
} else if(added_num_of_links == 5) {
printf("App : Delete a link\n");
sixtop_remove_link((linkaddr_t *)0xffff);
sf_simple_remove_links(&n->addr);
}
added_num_of_links++;
}

View File

@ -31,11 +31,6 @@
#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
@ -66,7 +61,7 @@
/* IEEE802.15.4 frame version */
#undef FRAME802154_CONF_VERSION
#define FRAME802154_CONF_VERSION FRAME802154_IEEE802154E_2012
#define FRAME802154_CONF_VERSION FRAME802154_IEEE802154_2015
/* TSCH and RPL callbacks */
#define RPL_CALLBACK_PARENT_SWITCH tsch_rpl_callback_parent_switch
@ -96,10 +91,9 @@
/******************* 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
/* TSCH logging. */
#undef TSCH_LOG_CONF_PER_SLOT
#define TSCH_LOG_CONF_PER_SLOT 1
/* IEEE802.15.4 PANID */
#undef IEEE802154_CONF_PANID
@ -127,19 +121,6 @@
#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 **************/
/*******************************************************/

View File

@ -0,0 +1,621 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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
* A 6P Simple Schedule Function
* \author
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#include "contiki-lib.h"
#include "lib/assert.h"
#include "net/mac/tsch/tsch-schedule.h"
#include "net/mac/tsch/sixtop/sixtop.h"
#include "net/mac/tsch/sixtop/sixp.h"
#include "net/mac/tsch/sixtop/sixp-nbr.h"
#include "net/mac/tsch/sixtop/sixp-pkt.h"
#include "net/mac/tsch/sixtop/sixp-trans.h"
#include "sf-simple.h"
#define DEBUG DEBUG_PRINT
#include "net/net-debug.h"
typedef struct {
uint16_t timeslot_offset;
uint16_t channel_offset;
} sf_simple_cell_t;
static const uint16_t slotframe_handle = 0;
static uint8_t res_storage[4 + SF_SIMPLE_MAX_LINKS * 4];
static uint8_t req_storage[4 + SF_SIMPLE_MAX_LINKS * 4];
static void read_cell(const uint8_t *buf, sf_simple_cell_t *cell);
static void print_cell_list(const uint8_t *cell_list, uint16_t cell_list_len);
static void add_links_to_schedule(const linkaddr_t *peer_addr,
uint8_t link_option,
const uint8_t *cell_list,
uint16_t cell_list_len);
static void remove_links_to_schedule(const uint8_t *cell_list,
uint16_t cell_list_len);
static void add_response_sent_callback(void *arg, uint16_t arg_len,
const linkaddr_t *dest_addr,
sixp_output_status_t status);
static void delete_response_sent_callback(void *arg, uint16_t arg_len,
const linkaddr_t *dest_addr,
sixp_output_status_t status);
static void add_req_input(const uint8_t *body, uint16_t body_len,
const linkaddr_t *peer_addr);
static void delete_req_input(const uint8_t *body, uint16_t body_len,
const linkaddr_t *peer_addr);
static void input(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t *body, uint16_t body_len,
const linkaddr_t *src_addr);
static void request_input(sixp_pkt_cmd_t cmd,
const uint8_t *body, uint16_t body_len,
const linkaddr_t *peer_addr);
static void response_input(sixp_pkt_rc_t rc,
const uint8_t *body, uint16_t body_len,
const linkaddr_t *peer_addr);
/*
* scheduling policy:
* add: if and only if all the requested cells are available, accept the request
* delete: if and only if all the requested cells are in use, accept the request
*/
static void
read_cell(const uint8_t *buf, sf_simple_cell_t *cell)
{
cell->timeslot_offset = buf[0] + (buf[1] << 8);
cell->channel_offset = buf[2] + (buf[3] << 8);
}
static void
print_cell_list(const uint8_t *cell_list, uint16_t cell_list_len)
{
uint16_t i;
sf_simple_cell_t cell;
for(i = 0; i < (cell_list_len / sizeof(cell)); i++) {
read_cell(&cell_list[i], &cell);
PRINTF("%u ", cell.timeslot_offset);
}
}
static void
add_links_to_schedule(const linkaddr_t *peer_addr, uint8_t link_option,
const uint8_t *cell_list, uint16_t cell_list_len)
{
/* add only the first valid cell */
sf_simple_cell_t cell;
struct tsch_slotframe *slotframe;
int i;
assert(cell_list != NULL);
slotframe = tsch_schedule_get_slotframe_by_handle(slotframe_handle);
if(slotframe == NULL) {
return;
}
for(i = 0; i < (cell_list_len / sizeof(cell)); i++) {
read_cell(&cell_list[i], &cell);
if(cell.timeslot_offset == 0xffff) {
continue;
}
PRINTF("sf-simple: Schedule link %d as %s with node %u\n",
cell.timeslot_offset,
link_option == LINK_OPTION_RX ? "RX" : "TX",
peer_addr->u8[7]);
tsch_schedule_add_link(slotframe,
link_option, LINK_TYPE_NORMAL, peer_addr,
cell.timeslot_offset, cell.channel_offset);
break;
}
}
static void
remove_links_to_schedule(const uint8_t *cell_list, uint16_t cell_list_len)
{
/* remove all the cells */
sf_simple_cell_t cell;
struct tsch_slotframe *slotframe;
int i;
assert(cell_list != NULL);
slotframe = tsch_schedule_get_slotframe_by_handle(slotframe_handle);
if(slotframe == NULL) {
return;
}
for(i = 0; i < (cell_list_len / sizeof(cell)); i++) {
read_cell(&cell_list[i], &cell);
if(cell.timeslot_offset == 0xffff) {
continue;
}
tsch_schedule_remove_link_by_timeslot(slotframe,
cell.timeslot_offset);
}
}
static void
add_response_sent_callback(void *arg, uint16_t arg_len,
const linkaddr_t *dest_addr,
sixp_output_status_t status)
{
uint8_t *body = (uint8_t *)arg;
uint16_t body_len = arg_len;
const uint8_t *cell_list;
uint16_t cell_list_len;
sixp_nbr_t *nbr;
assert(body != NULL && dest_addr != NULL);
if(status == SIXP_OUTPUT_STATUS_SUCCESS &&
sixp_pkt_get_cell_list(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
&cell_list, &cell_list_len,
body, body_len) == 0 &&
(nbr = sixp_nbr_find(dest_addr)) != NULL) {
add_links_to_schedule(dest_addr, LINK_OPTION_RX,
cell_list, cell_list_len);
sixp_nbr_advance_grx(nbr);
}
}
static void
delete_response_sent_callback(void *arg, uint16_t arg_len,
const linkaddr_t *dest_addr,
sixp_output_status_t status)
{
uint8_t *body = (uint8_t *)arg;
uint16_t body_len = arg_len;
const uint8_t *cell_list;
uint16_t cell_list_len;
sixp_nbr_t *nbr;
assert(body != NULL && dest_addr != NULL);
if(status == SIXP_OUTPUT_STATUS_SUCCESS &&
sixp_pkt_get_cell_list(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
&cell_list, &cell_list_len,
body, body_len) == 0 &&
(nbr = sixp_nbr_find(dest_addr)) != NULL) {
remove_links_to_schedule(cell_list, cell_list_len);
sixp_nbr_advance_grx(nbr);
}
}
static void
add_req_input(const uint8_t *body, uint16_t body_len, const linkaddr_t *peer_addr)
{
uint8_t i;
sf_simple_cell_t cell;
struct tsch_slotframe *slotframe;
int feasible_link;
uint8_t num_cells;
const uint8_t *cell_list;
uint16_t cell_list_len;
uint16_t res_len;
assert(body != NULL && peer_addr != NULL);
if(sixp_pkt_get_num_cells(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
&num_cells,
body, body_len) != 0 ||
sixp_pkt_get_cell_list(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
&cell_list, &cell_list_len,
body, body_len) != 0) {
PRINTF("sf-simple: Parse error on add request\n");
return;
}
PRINTF("sf-simple: Received a 6P Add Request for %d links from node %d with LinkList : ",
num_cells, peer_addr->u8[7]);
print_cell_list(cell_list, cell_list_len);
PRINTF("\n");
slotframe = tsch_schedule_get_slotframe_by_handle(slotframe_handle);
if(slotframe == NULL) {
return;
}
if(num_cells > 0 && cell_list_len > 0) {
memset(res_storage, 0, sizeof(res_storage));
res_len = 0;
/* checking availability for requested slots */
for(i = 0, feasible_link = 0;
i < cell_list_len && feasible_link < num_cells;
i += sizeof(cell)) {
read_cell(&cell_list[i], &cell);
if(tsch_schedule_get_link_by_timeslot(slotframe,
cell.timeslot_offset) == NULL) {
sixp_pkt_set_cell_list(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
(uint8_t *)&cell, sizeof(cell),
feasible_link,
res_storage, sizeof(res_storage));
res_len += sizeof(cell);
feasible_link++;
}
}
if(feasible_link == num_cells) {
/* Links are feasible. Create Link Response packet */
PRINTF("sf-simple: Send a 6P Response to node %d\n", peer_addr->u8[7]);
sixp_output(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
SF_SIMPLE_SFID,
res_storage, res_len, peer_addr,
add_response_sent_callback, res_storage, res_len);
}
}
}
static void
delete_req_input(const uint8_t *body, uint16_t body_len,
const linkaddr_t *peer_addr)
{
uint8_t i;
sf_simple_cell_t cell;
struct tsch_slotframe *slotframe;
uint8_t num_cells;
const uint8_t *cell_list;
uint16_t cell_list_len;
uint16_t res_len;
int removed_link;
assert(body != NULL && peer_addr != NULL);
if(sixp_pkt_get_num_cells(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE,
&num_cells,
body, body_len) != 0 ||
sixp_pkt_get_cell_list(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE,
&cell_list, &cell_list_len,
body, body_len) != 0) {
PRINTF("sf-simple: Parse error on delete request\n");
return;
}
PRINTF("sf-simple: Received a 6P Delete Request for %d links from node %d with LinkList : ",
num_cells, peer_addr->u8[7]);
print_cell_list(cell_list, cell_list_len);
PRINTF("\n");
slotframe = tsch_schedule_get_slotframe_by_handle(slotframe_handle);
if(slotframe == NULL) {
return;
}
memset(res_storage, 0, sizeof(res_storage));
res_len = 0;
if(num_cells > 0 && cell_list_len > 0) {
/* ensure before delete */
for(i = 0, removed_link = 0; i < (cell_list_len / sizeof(cell)); i++) {
read_cell(&cell_list[i], &cell);
if(tsch_schedule_get_link_by_timeslot(slotframe,
cell.timeslot_offset) != NULL) {
sixp_pkt_set_cell_list(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
(uint8_t *)&cell, sizeof(cell),
removed_link,
res_storage, sizeof(res_storage));
res_len += sizeof(cell);
}
}
}
/* Links are feasible. Create Link Response packet */
PRINTF("sf-simple: Send a 6P Response to node %d\n", peer_addr->u8[7]);
sixp_output(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
SF_SIMPLE_SFID,
res_storage, res_len, peer_addr,
delete_response_sent_callback, res_storage, res_len);
}
static void
input(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t *body, uint16_t body_len, const linkaddr_t *src_addr)
{
assert(body != NULL && body != NULL);
switch(type) {
case SIXP_PKT_TYPE_REQUEST:
request_input(code.cmd, body, body_len, src_addr);
break;
case SIXP_PKT_TYPE_RESPONSE:
response_input(code.cmd, body, body_len, src_addr);
break;
default:
/* unsupported */
break;
}
}
static void
request_input(sixp_pkt_cmd_t cmd,
const uint8_t *body, uint16_t body_len,
const linkaddr_t *peer_addr)
{
assert(body != NULL && peer_addr != NULL);
switch(cmd) {
case SIXP_PKT_CMD_ADD:
add_req_input(body, body_len, peer_addr);
break;
case SIXP_PKT_CMD_DELETE:
delete_req_input(body, body_len, peer_addr);
break;
default:
/* unsupported request */
break;
}
}
static void
response_input(sixp_pkt_rc_t rc,
const uint8_t *body, uint16_t body_len,
const linkaddr_t *peer_addr)
{
const uint8_t *cell_list;
uint16_t cell_list_len;
sixp_nbr_t *nbr;
sixp_trans_t *trans;
assert(body != NULL && peer_addr != NULL);
if((nbr = sixp_nbr_find(peer_addr)) == NULL ||
(trans = sixp_trans_find(peer_addr)) == NULL) {
return;
}
if(rc == SIXP_PKT_RC_SUCCESS) {
switch(sixp_trans_get_cmd(trans)) {
case SIXP_PKT_CMD_ADD:
if(sixp_pkt_get_cell_list(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
&cell_list, &cell_list_len,
body, body_len) != 0) {
PRINTF("sf-simple: Parse error on add response\n");
return;
}
PRINTF("sf-simple: Received a 6P Add Response with LinkList : ");
print_cell_list(cell_list, cell_list_len);
PRINTF("\n");
add_links_to_schedule(peer_addr, LINK_OPTION_TX,
cell_list, cell_list_len);
sixp_nbr_advance_gtx(nbr);
break;
case SIXP_PKT_CMD_DELETE:
if(sixp_pkt_get_cell_list(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
&cell_list, &cell_list_len,
body, body_len) != 0) {
PRINTF("sf-simple: Parse error on add response\n");
return;
}
PRINTF("sf-simple: Received a 6P Delete Response with LinkList : ");
print_cell_list(cell_list, cell_list_len);
PRINTF("\n");
remove_links_to_schedule(cell_list, cell_list_len);
sixp_nbr_advance_gtx(nbr);
break;
case SIXP_PKT_CMD_STATUS:
case SIXP_PKT_CMD_LIST:
case SIXP_PKT_CMD_CLEAR:
default:
PRINTF("sf-simple: unsupported response\n");
}
}
}
/*---------------------------------------------------------------------------*/
/* Initiates a Sixtop Link addition
*/
int
sf_simple_add_links(linkaddr_t *peer_addr, uint8_t num_links)
{
uint8_t i = 0, index = 0;
struct tsch_slotframe *sf =
tsch_schedule_get_slotframe_by_handle(slotframe_handle);
uint8_t req_len;
sf_simple_cell_t cell_list[SF_SIMPLE_MAX_LINKS];
/* Flag to prevent repeated slots */
uint8_t slot_check = 1;
uint16_t random_slot = 0;
assert(peer_addr != NULL && sf != NULL);
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) {
/* To prevent repeated slots */
for(i = 0; i < index; i++) {
if(cell_list[i].timeslot_offset != 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) {
cell_list[index].timeslot_offset = random_slot;
cell_list[index].channel_offset = 0;
index++;
slot_check++;
} else if(slot_check > TSCH_SCHEDULE_DEFAULT_LENGTH) {
PRINTF("sf-simple:! Number of trials for free slot exceeded...\n");
return -1;
break; /* exit while loop */
}
}
} while(index < SF_SIMPLE_MAX_LINKS);
/* Create a Sixtop Add Request. Return 0 if Success */
if(index == 0 ) {
return -1;
}
memset(req_storage, 0, sizeof(req_storage));
if(sixp_pkt_set_cell_options(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
SIXP_PKT_CELL_OPTION_TX,
req_storage,
sizeof(req_storage)) != 0 ||
sixp_pkt_set_num_cells(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
num_links,
req_storage,
sizeof(req_storage)) != 0 ||
sixp_pkt_set_cell_list(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
(const uint8_t *)cell_list,
index * sizeof(sf_simple_cell_t), 0,
req_storage, sizeof(req_storage)) != 0) {
PRINTF("sf-simple: Build error on add request\n");
return -1;
}
/* The length of fixed part is 4 bytes: Metadata, CellOptions, and NumCells */
req_len = 4 + index * sizeof(sf_simple_cell_t);
sixp_output(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
SF_SIMPLE_SFID,
req_storage, req_len, peer_addr,
NULL, NULL, 0);
PRINTF("sf-simple: Send a 6P Add Request for %d links to node %d with LinkList : ",
num_links, peer_addr->u8[7]);
print_cell_list((const uint8_t *)cell_list, index * sizeof(sf_simple_cell_t));
PRINTF("\n");
return 0;
}
/*---------------------------------------------------------------------------*/
/* Initiates a Sixtop Link deletion
*/
int
sf_simple_remove_links(linkaddr_t *peer_addr)
{
uint8_t i = 0, index = 0;
struct tsch_slotframe *sf =
tsch_schedule_get_slotframe_by_handle(slotframe_handle);
struct tsch_link *l;
uint16_t req_len;
sf_simple_cell_t cell;
assert(peer_addr != NULL && sf != NULL);
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, peer_addr)) && (l->link_options == LINK_OPTION_TX)) {
/* This link is scheduled as a TX link to the specified neighbor */
cell.timeslot_offset = i;
cell.channel_offset = l->channel_offset;
index++;
break; /* delete atmost one */
}
}
}
if(index == 0) {
return -1;
}
memset(req_storage, 0, sizeof(req_storage));
if(sixp_pkt_set_num_cells(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE,
1,
req_storage,
sizeof(req_storage)) != 0 ||
sixp_pkt_set_cell_list(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE,
(const uint8_t *)&cell, sizeof(cell),
0,
req_storage, sizeof(req_storage)) != 0) {
PRINTF("sf-simple: Build error on add request\n");
return -1;
}
/* The length of fixed part is 4 bytes: Metadata, CellOptions, and NumCells */
req_len = 4 + sizeof(sf_simple_cell_t);
sixp_output(SIXP_PKT_TYPE_REQUEST, (sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_DELETE,
SF_SIMPLE_SFID,
req_storage, req_len, peer_addr,
NULL, NULL, 0);
PRINTF("sf-simple: Send a 6P Delete Request for %d links to node %d with LinkList : ",
1, peer_addr->u8[7]);
print_cell_list((const uint8_t *)&cell, sizeof(cell));
PRINTF("\n");
return 0;
}
const sixtop_sf_t sf_simple_driver = {
SF_SIMPLE_SFID,
CLOCK_SECOND,
NULL,
input,
NULL
};

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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
* A 6P Simple Schedule Function
* \author
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#ifndef _SIXTOP_SF_SIMPLE_H_
#define _SIXTOP_SF_SIMPLE_H_
#include "net/linkaddr.h"
int sf_simple_add_links(linkaddr_t *peer_addr, uint8_t num_links);
int sf_simple_remove_links(linkaddr_t *peer_addr);
#define SF_SIMPLE_MAX_LINKS 3
#define SF_SIMPLE_SFID 0xf0
extern const sixtop_sf_t sf_simple_driver;
#endif /* !_SIXTOP_SF_SIMPLE_H_ */

View File

@ -62,6 +62,7 @@ enum ieee802154e_header_ie_id {
enum ieee802154e_payload_ie_id {
PAYLOAD_IE_ESDU = 0,
PAYLOAD_IE_MLME,
PAYLOAD_IE_IETF = 0x5,
PAYLOAD_IE_LIST_TERMINATION = 0xf,
};
@ -81,6 +82,11 @@ enum ieee802154e_mlme_long_subie_id {
MLME_LONG_IE_TSCH_CHANNEL_HOPPING_SEQUENCE = 0x9,
};
#include <net/mac/tsch/sixtop/sixtop.h>
enum ieee802154e_ietf_subie_id {
IETF_IE_6TOP = SIXTOP_SUBIE_ID,
};
#define WRITE16(buf, val) \
do { ((uint8_t *)(buf))[0] = (val) & 0xff; \
((uint8_t *)(buf))[1] = ((val) >> 8) & 0xff; } while(0);
@ -194,6 +200,21 @@ frame80215e_create_ie_payload_list_termination(uint8_t *buf, int len,
}
}
#if TSCH_WITH_SIXTOP
/* Payload IE. 6top. Used to nest sub-IEs */
int
frame80215e_create_ie_ietf(uint8_t *buf, int len, struct ieee802154_ies *ies)
{
if(len >= 2 && ies != NULL) {
create_payload_ie_descriptor(buf,
PAYLOAD_IE_IETF,
ies->sixtop_ie_content_len);
return 2 + ies->sixtop_ie_content_len;
}
return -1;
}
#endif /* TSCH_WITH_SIXTOP */
/* Payload IE. MLME. Used to nest sub-IEs */
int
frame80215e_create_ie_mlme(uint8_t *buf, int len,
@ -531,6 +552,29 @@ frame802154e_parse_information_elements(const uint8_t *buf, uint8_t buf_size,
len = 0; /* Reset len as we want to read subIEs and not jump over them */
LOG_DBG("entering MLME ie with len %u\n", nested_mlme_len);
break;
#if TSCH_WITH_SIXTOP
case PAYLOAD_IE_IETF:
switch(*buf) {
case IETF_IE_6TOP:
/*
* buf points to the Sub-ID field, a one-octet field, now;
* advance it by one and use the result as the head pointer of
* 6top IE Content.
*/
ies->sixtop_ie_content_ptr = buf + 1;
/*
* Similarly as above, subtract 1 (one octet) from len, which
* includes the length of Sub-ID field, and use the result as
* the length of 6top IE Content.
*/
ies->sixtop_ie_content_len = len - 1;
break;
default:
LOG_ERR("frame802154e: unsupported IETF sub-IE %u\n", *buf);
break;
}
break;
#endif /* TSCH_WITH_SIXTOP */
case PAYLOAD_IE_LIST_TERMINATION:
LOG_DBG("payload ie list termination %u\n", len);
return (len == 0) ? buf + len - start : -1;

View File

@ -42,6 +42,7 @@
#include "contiki.h"
/* We need definitions from tsch-private.h for TSCH-specific information elements */
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/tsch-private.h"
#define FRAME802154E_IE_MAX_LINKS 4
@ -80,6 +81,11 @@ struct ieee802154_ies {
/* We include and parse only the sequence len and list and omit unused fields */
uint16_t ie_hopping_sequence_len;
uint8_t ie_hopping_sequence_list[TSCH_HOPPING_SEQUENCE_MAX_LEN];
#if TSCH_WITH_SIXTOP
/* Payload Sixtop IE */
const uint8_t *sixtop_ie_content_ptr;
uint16_t sixtop_ie_content_len;
#endif /* TSCH_WITH_SIXTOP */
};
/** Insert various Information Elements **/
@ -97,6 +103,11 @@ int frame80215e_create_ie_header_list_termination_2(uint8_t *buf, int len,
/* Payload IE. List termination */
int frame80215e_create_ie_payload_list_termination(uint8_t *buf, int len,
struct ieee802154_ies *ies);
#if TSCH_WITH_SIXTOP
/* Payload IE. 6top. Used to nest sub-IEs */
int frame80215e_create_ie_ietf(uint8_t *buf, int len,
struct ieee802154_ies *ies);
#endif /* TSCH_WITH_SIXTOP */
/* Payload IE. MLME. Used to nest sub-IEs */
int frame80215e_create_ie_mlme(uint8_t *buf, int len,
struct ieee802154_ies *ies);

View File

@ -1,64 +1,103 @@
# [EXPERIMENTAL] 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.
# 6TiSCH Operation Sublayer (6top)
This is a Contiki implementation of 6top, developed by:
## **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)
- Shalu R, CDAC, shalur@cdac.in, github user: [shalurajendran](https://github.com/shalurajendran)
- Lijo Thomas, CDAC, lijo@cdac.in
- Yasuyuki Tanaka
## **Features**
It supports 6P (6top Protocol) of [draft-03](draft-ietf-6tisch-6top-protocol-03)
except for concurrent 6P transactions described in [Section
4.3.3](https://tools.ietf.org/html/draft-ietf-6tisch-6top-protocol-03#section-4.3.3).
This implementation includes:
## Code Structure
- 6top protocol(6P)
- 6P Add
- 6P Delete
- 2-step 6top Transaction
| File | Contents |
|-----------------|--------------------------------|
| sixtop.[ch] | 6top external APIs |
| sixp.[ch] | 6P I/O APIs |
| sixp-nbr.[ch] | 6P Neighbor Management APIs |
| sixp-pkt.[ch] | 6P Packet Manipulation APIs |
| sixp-trans.[ch] | 6P Transaction Management APIs |
| sixp-conf.h | 6P Configuration Parameters |
The code has been tested on Zolertia Z1 (z1, tested in cooja only) platform.
## Configuration Paramters
## **Code structure**
| Parameter | Meaning | Default Value |
|--------------------------------------|----------------------------------------------|---------------|
| SIXTOP_CONF_MAX_SCHEDULING_FUNCTIONS | The maximum number of SFs installed in 6top | 1 |
| SIXTOP_CONF_MAX_TRANSACTIONS | The maximum number of transactions at a time | 1 |
The 6top frame format is included in:
## Caveat
- core/net/mac/frame802154-ie.[ch]: Modified to include Sixtop Information Elements
At this moment, allocated 6P neighbor states never be deleted since 6P has no
way to decide to delete them. 6P neighbor state consists of SeqNum to be used
for a next reqeust, GTX, and GRX (defined in sixp-nbr.c).
6top is implemented in:
Once the number of 6P neighbor states reaches to the `SIXTOP_6P_MAX_NEIGHBORS`,
a transaction with a new neighbor may fail due to failure in allocating a 6P
neighbor state or schedule generation inconsistency.
- core/net/mac/tsch/sixtop/sixtop.[ch]: 6top interface and 6top protocol(6P addition and deletion), handling of 6P Requests and Response
## Example
TSCH file modified:
An example using 6top is provided under `examples/ipv6/rpl-tsch-sxitop/`.
- core/net/mac/tsch/tsch.[ch]: Modified to include Sixtop module
A simple Scheduling Function (SF) is implemented in `sf-simple.[ch]`. This SF
does not have bandwidth monitoring mechanism nor bandwidth adaptation
mechanism. Instead, the SF provides APIs so that a user process can add or
remove cells dynamically. A sample user process implementation using the SF is
found in `node-sixtop.c`, which is tested with `rpl-tsch-sixtop-z1.csc`.
## Test
## **Using 6top**
6top or 6P related tests are implemented under `regression-tests/26-6tisch`.
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.
## Using 6top
To use 6top, make sure your platform supports TSCH and have sufficient memory.
In order to use 6top with your system, `sixtop` module must be built together in
addition to [TSCH](../).
To add 6top to your application, first include the Sixtop module in your Makefile with:
Enable TSCH, then set 1 to `TSCH_CONF_WITH_SIXTOP`, typically, in your
`project-conf.h`:
MODULES += core/net/mac/tsch/sixtop
```C
#undef TSCH_CONF_WITH_SIXTOP
#define TSCH_CONF_WITH_SIXTOP 1
```
Also enable the sixtop functionalities in your project-conf.h file with
Next, add `sixtop` into `MODULES` in your Makefile:
#undef TSCH_CONF_WITH_SIXTOP
#define TSCH_CONF_WITH_SIXTOP 1
```Makefile
MODULES += core/net/mac/tsch/sixtop
```
## **Additional documentation**
For now, the simple SF mentioned above is only one SF shipped in the code
base. You may have to implement your own SF.
## Implementing a Scheduling Function
Scheduling Function (SF) is represented with `sixtop_sf_t`, which defined in
`sixtop.h`. An SF can be added into 6top by `sixtop_add_sf()`. After the
addition, a handler defined in `sixtop_sf_t` is invoked on a correspondent
event, for example, reception of a 6P request or timeout of an ongoing
transaction.
SF can send a 6P packet by `sixp_output()`. After every Add or Delete operation,
SF needs to advance schedule generation counter associated with the peer by
`sixp_advance_generation()`, counter which is maintaeind by 6P. Otherwise, SF
will not able to perform any command request other than Clear due to schedule
generation inconsistency.
## References
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)
2. [6top Protocol (6P)](https://tools.ietf.org/html/draft-ietf-6tisch-6top-protocol)

View File

@ -0,0 +1,240 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* Neighbor Management for 6top Protocol (6P)
* \author
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#include "contiki-lib.h"
#include "lib/assert.h"
#include "net/nbr-table.h"
#include "sixp.h"
#define DEBUG DEBUG_PRINT
#include "net/net-debug.h"
/**
* \brief 6P Neighbor Data Structure (for internal use)
*
* XXX: for now, we have one nbr object per neighbor, which is shared with
* multiple SFs. It's unclear whether we should use a different generation
* counter for each SFs.
*/
typedef struct sixp_nbr {
struct sixp_nbr *next;
linkaddr_t addr;
uint8_t next_seqno;
uint8_t gtx;
uint8_t grx;
} sixp_nbr_t;
static int advance_generation_counter(uint8_t *gc);
NBR_TABLE(sixp_nbr_t, sixp_nbrs);
/*---------------------------------------------------------------------------*/
static int
advance_generation_counter(uint8_t *gc)
{
assert(gc != NULL);
if(gc == NULL) {
return -1;
}
switch(*gc) {
case 0x00:
case 0x02:
*gc = 0x01;
break;
case 0x01:
*gc = 0x02;
break;
default:
/* unexpected condition */
PRINTF("6P-nbr: advance_generation_counter() has unexpected gc %02x\n",
*gc);
return -1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
sixp_nbr_t *
sixp_nbr_find(const linkaddr_t *addr)
{
assert(addr != NULL);
if(addr == NULL) {
return NULL;
}
return (sixp_nbr_t *)nbr_table_get_from_lladdr(sixp_nbrs, addr);
}
/*---------------------------------------------------------------------------*/
sixp_nbr_t *
sixp_nbr_alloc(const linkaddr_t *addr)
{
sixp_nbr_t *nbr;
assert(addr != NULL);
if(addr == NULL) {
PRINTF("6P-nbr: sixp_nbr_alloc() fails because of invalid argument\n");
return NULL;
}
if(sixp_nbr_find(addr) != NULL) {
PRINTF("6P-nbr: sixp_nbr_alloc() fails because of duplication [peer_addr:");
PRINTLLADDR((const uip_lladdr_t *)addr);
PRINTF("]\n");
return NULL;
}
if((nbr = (sixp_nbr_t *)nbr_table_add_lladdr(sixp_nbrs,
addr,
NBR_TABLE_REASON_SIXTOP,
NULL)) == NULL) {
PRINTF("6P-nbr: sixp_nbr_alloc() fails to add nbr because of no memory\n");
return NULL;
}
linkaddr_copy(&nbr->addr, addr);
nbr->next_seqno = SIXP_INITIAL_SEQUENCE_NUMBER;
nbr->gtx = 0;
nbr->grx = 0;
return nbr;
}
/*---------------------------------------------------------------------------*/
void
sixp_nbr_free(sixp_nbr_t *nbr)
{
assert(nbr != NULL);
if(nbr != NULL) {
(void)nbr_table_remove(sixp_nbrs, nbr);
}
}
/*---------------------------------------------------------------------------*/
int16_t
sixp_nbr_get_gtx(sixp_nbr_t *nbr)
{
assert(nbr != NULL);
if(nbr == NULL) {
PRINTF("6P-nbr: sixp_nbr_get_gtx() fails because of invalid argument\n");
return -1;
}
return nbr->gtx;
}
/*---------------------------------------------------------------------------*/
int8_t
sixp_nbr_get_grx(sixp_nbr_t *nbr)
{
assert(nbr != NULL);
if(nbr == NULL) {
PRINTF("6P-nbr: sixp_nbr_get_grx() fails because of invalid argument\n");
return -1;
}
return nbr->grx;
}
/*---------------------------------------------------------------------------*/
int
sixp_nbr_advance_gtx(sixp_nbr_t *nbr)
{
assert(nbr != NULL);
if(nbr == NULL) {
PRINTF("6P-nbr: sixp_nbr_advance_gtx() fails because of invalid arg\n");
return -1;
}
return advance_generation_counter(&nbr->gtx);
}
/*---------------------------------------------------------------------------*/
int
sixp_nbr_advance_grx(sixp_nbr_t *nbr)
{
assert(nbr != NULL);
if(nbr == NULL) {
PRINTF("6P-nbr: sixp_nbr_advance_grx() fails because of invalid arg\n");
return -1;
}
return advance_generation_counter(&nbr->grx);
}
/*---------------------------------------------------------------------------*/
int
sixp_nbr_get_next_seqno(sixp_nbr_t *nbr)
{
assert(nbr != NULL);
if(nbr == NULL) {
PRINTF("6P-nbr: sixp_nbr_get_next_seqno() fails because of invalid arg\n");
return -1;
}
return nbr->next_seqno;
}
/*---------------------------------------------------------------------------*/
int
sixp_nbr_increment_next_seqno(sixp_nbr_t *nbr)
{
assert(nbr != NULL);
if(nbr == NULL) {
PRINTF("6P-nbr: sixp_nbr_increment_next_seqno() fails; invalid arg\n");
return -1;
}
nbr->next_seqno++;
if(nbr->next_seqno > 0x0f) {
/*
* nbr->next_seqno, which represents a value of the SeqNum field, won't be
* larger than 0x0f since he length of SeqNum field is 4 bits.
*/
nbr->next_seqno = 0;
}
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_nbr_init(void)
{
sixp_nbr_t *nbr, *next_nbr;
if(nbr_table_is_register(sixp_nbrs) == 0) {
nbr_table_register(sixp_nbrs, NULL);
} else {
/* remove all the existing nbrs */
nbr = (sixp_nbr_t *)nbr_table_head(sixp_nbrs);
while(nbr != NULL) {
next_nbr = (sixp_nbr_t *)nbr_table_next(sixp_nbrs, nbr);
sixp_nbr_free(nbr);
nbr = next_nbr;
}
}
return 0;
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* Neighbor Management APIs for 6top Protocol (6P)
* \author
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#include "sixp-pkt.h"
typedef struct sixp_nbr sixp_nbr_t;
/**
* \brief Find a neighbor
* \param addr The MAC address of a neighbor
* \return The pointer to a neighbor, NULL on failure
*/
sixp_nbr_t *sixp_nbr_find(const linkaddr_t *addr);
/**
* \brief Allocate a neighbor
* \param addr The MAC address of a neighbor
* \return The pointer to a allocated neighbor, NULL on failure
*/
sixp_nbr_t *sixp_nbr_alloc(const linkaddr_t *addr);
/**
* \brief Free a neighbor
* \param nbr The pointer to a neighbor to free
*/
void sixp_nbr_free(sixp_nbr_t *nbr);
/**
* \brief Return GTX of a neighbor
* \param nbr The pointer to a neighbor
* \return A value of GTX, -1 on failure
*/
int16_t sixp_nbr_get_gtx(sixp_nbr_t *nbr);
/**
* \brief Return GRX of a neighbor
* \param nbr The pointer to a neighbor
* \return A value of GRX
*/
int16_t sixp_nbr_get_grx(sixp_nbr_t *nbr);
/**
* \brief Advance GTX of a neighbor
* \param nbr The pointer to a neighbor
* \return 0 on success, -1 on failure
*/
int sixp_nbr_advance_gtx(sixp_nbr_t *nbr);
/**
* \brief Advance GRX of a neighbor
* \param nbr The pointer to a neighbor
* \return 0 on success, -1 on failure
*/
int sixp_nbr_advance_grx(sixp_nbr_t *nbr);
/**
* \brief Get the next sequence number of a neighbor
* \param nbr The pointer to a neighbor
* \return A sequence number to use for a next request, -1 on failure
*/
int16_t sixp_nbr_get_next_seqno(sixp_nbr_t *nbr);
/**
* \brief Increment the next sequence number of a neighbor
* \param nbr The pointer to a neighbor
* \return 0 on success, -1 on failure
*/
int sixp_nbr_increment_next_seqno(sixp_nbr_t *nbr);
/**
* \brief Initialize 6p Neighbor Table
*/
int sixp_nbr_init(void);
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,780 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka.
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* 6top Protocol (6P) Packet Manipulation
* \author
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#include "contiki.h"
#include "contiki-lib.h"
#include "lib/assert.h"
#include "net/packetbuf.h"
#include "net/mac/tsch/tsch.h"
#include "sixp.h"
#include "sixp-pkt.h"
#define DEBUG DEBUG_PRINT
#include "net/net-debug.h"
static int32_t get_metadata_offset(sixp_pkt_type_t type, sixp_pkt_code_t code);
static int32_t get_cell_options_offset(sixp_pkt_type_t type,
sixp_pkt_code_t code);
static int32_t get_num_cells_offset(sixp_pkt_type_t type, sixp_pkt_code_t code);
static int32_t get_reserved_offset(sixp_pkt_type_t type, sixp_pkt_code_t code);
static int32_t get_offset_offset(sixp_pkt_type_t type, sixp_pkt_code_t code);
static int32_t get_max_num_cells_offset(sixp_pkt_type_t type,
sixp_pkt_code_t code);
static int32_t get_cell_list_offset(sixp_pkt_type_t type, sixp_pkt_code_t code);
/*---------------------------------------------------------------------------*/
static int32_t
get_metadata_offset(sixp_pkt_type_t type, sixp_pkt_code_t code)
{
if(type == SIXP_PKT_TYPE_REQUEST) {
return 0; /* offset */
}
return -1;
}
/*---------------------------------------------------------------------------*/
static int32_t
get_cell_options_offset(sixp_pkt_type_t type, sixp_pkt_code_t code)
{
if(type == SIXP_PKT_TYPE_REQUEST &&
(code.cmd == SIXP_PKT_CMD_ADD ||
code.cmd == SIXP_PKT_CMD_DELETE ||
code.cmd == SIXP_PKT_CMD_STATUS ||
code.cmd == SIXP_PKT_CMD_LIST)) {
return sizeof(sixp_pkt_metadata_t);
}
return -1;
}
/*---------------------------------------------------------------------------*/
static int32_t
get_num_cells_offset(sixp_pkt_type_t type, sixp_pkt_code_t code)
{
if(type == SIXP_PKT_TYPE_REQUEST &&
(code.value == SIXP_PKT_CMD_ADD || code.value == SIXP_PKT_CMD_DELETE)) {
return sizeof(sixp_pkt_metadata_t) + sizeof(sixp_pkt_cell_options_t);
} else if(type == SIXP_PKT_TYPE_RESPONSE &&
code.value == SIXP_PKT_RC_SUCCESS) {
return 0;
}
return -1;
}
/*---------------------------------------------------------------------------*/
static int32_t
get_reserved_offset(sixp_pkt_type_t type, sixp_pkt_code_t code)
{
if(type == SIXP_PKT_TYPE_REQUEST &&
code.value == SIXP_PKT_CMD_LIST) {
return sizeof(sixp_pkt_metadata_t) + sizeof(sixp_pkt_cell_options_t);
}
return -1;
}
/*---------------------------------------------------------------------------*/
static int32_t
get_offset_offset(sixp_pkt_type_t type, sixp_pkt_code_t code)
{
if(type == SIXP_PKT_TYPE_REQUEST &&
code.value == SIXP_PKT_CMD_LIST) {
return (sizeof(sixp_pkt_metadata_t) +
sizeof(sixp_pkt_cell_options_t) +
sizeof(sixp_pkt_reserved_t));
}
return -1;
}
/*---------------------------------------------------------------------------*/
static int32_t
get_max_num_cells_offset(sixp_pkt_type_t type, sixp_pkt_code_t code)
{
if(type == SIXP_PKT_TYPE_REQUEST &&
code.value == SIXP_PKT_CMD_LIST) {
return (sizeof(sixp_pkt_metadata_t) +
sizeof(sixp_pkt_cell_options_t) +
sizeof(sixp_pkt_reserved_t) +
sizeof(sixp_pkt_offset_t));
}
return -1;
}
/*---------------------------------------------------------------------------*/
static int32_t
get_cell_list_offset(sixp_pkt_type_t type, sixp_pkt_code_t code)
{
if(type == SIXP_PKT_TYPE_REQUEST && (code.value == SIXP_PKT_CMD_ADD ||
code.value == SIXP_PKT_CMD_DELETE)) {
return (sizeof(sixp_pkt_metadata_t) +
sizeof(sixp_pkt_cell_options_t) +
sizeof(sixp_pkt_num_cells_t));
} else if((type == SIXP_PKT_TYPE_RESPONSE ||
type == SIXP_PKT_TYPE_CONFIRMATION) &&
code.value == SIXP_PKT_RC_SUCCESS) {
return 0;
}
return -1;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_set_metadata(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_metadata_t metadata,
uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(body == NULL) {
PRINTF("6P-pkt: cannot set metadata; body is null\n");
return -1;
}
if((offset = get_metadata_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot set metadata [type=%u, code=%u], invalid type\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(metadata))) {
PRINTF("6P-pkt: cannot set metadata, body is too short [body_len=%u]\n",
body_len);
return -1;
}
/*
* Copy the content into the Metadata field as it is since 6P has no idea
* about the internal structure of the field.
*/
memcpy(body + offset, &metadata, sizeof(metadata));
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_get_metadata(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_metadata_t *metadata,
const uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(metadata == NULL || body == NULL) {
PRINTF("6P-pkt: cannot get metadata; invalid argument\n");
return -1;
}
if((offset = get_metadata_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot get metadata [type=%u, code=%u], invalid type\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(*metadata))) {
PRINTF("6P-pkt: cannot get metadata [type=%u, code=%u], body is too short\n",
type, code.value);
return -1;
}
/*
* Copy the content in the Metadata field as it is since 6P has no idea about
* the internal structure of the field.
*/
memcpy(metadata + offset, body, sizeof(*metadata));
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_set_cell_options(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_cell_options_t cell_options,
uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(body == NULL) {
PRINTF("6P-pkt: cannot set cell_options; body is null\n");
return -1;
}
if((offset = get_cell_options_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot set cell_options [type=%u, code=%u], invalid type\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(cell_options))) {
PRINTF("6P-pkt: cannot set cell_options, body is too short [body_len=%u]\n",
body_len);
return -1;
}
/* The CellOption field is an 8-bit bitfield */
memcpy(body + offset, &cell_options, sizeof(uint8_t));
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_get_cell_options(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_cell_options_t *cell_options,
const uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(cell_options == NULL || body == NULL) {
PRINTF("6P-pkt: cannot get cell_options; invalid argument\n");
return -1;
}
if((offset = get_cell_options_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot get cell_options [type=%u, code=%u], invalid type\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(*cell_options))) {
PRINTF("6P-pkt: cannot get cell_options, body is too short [body_len=%u]\n",
body_len);
return -1;
}
/* The CellOption field is an 8-bit bitfield */
memcpy(cell_options, body + offset, sizeof(uint8_t));
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_set_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_num_cells_t num_cells,
uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(body == NULL) {
PRINTF("6P-pkt: cannot set num_cells; body is null\n");
return -1;
}
if((offset = get_num_cells_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot set num_cells; ");
PRINTF("packet [type=%u, code=%u] won't have NumCells\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(num_cells))) {
PRINTF("6P-pkt: cannot set num_cells; body is too short\n");
return -1;
}
/* NumCells is an 8-bit unsigned integer */
memcpy(body + offset, &num_cells, sizeof(num_cells));
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_get_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_num_cells_t *num_cells,
const uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(num_cells == NULL || body == NULL) {
PRINTF("6P-pkt: cannot get num_cells; invalid argument\n");
return -1;
}
if((offset = get_num_cells_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot get num_cells; ");
PRINTF("packet [type=%u, code=%u] won't have NumCells\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(*num_cells))) {
PRINTF("6P-pkt: cannot get num_cells; body is too short\n");
return -1;
}
/* NumCells is an 8-bit unsigned integer */
memcpy(num_cells, body + offset, sizeof(uint8_t));
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_set_reserved(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_reserved_t reserved,
uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(body == NULL) {
PRINTF("6P-pkt: cannot set reserved; body is null\n");
return -1;
}
if((offset = get_reserved_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot set reserved; ");
PRINTF("packet [type=%u, code=%u] won't have Reserved\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(reserved))) {
PRINTF("6P-pkt: cannot set reserved; body is too short\n");
return -1;
}
/* The Reserved field is an 8-bit field */
memcpy(body + offset, &reserved, sizeof(uint8_t));
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_get_reserved(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_reserved_t *reserved,
const uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(reserved == NULL || body == NULL) {
PRINTF("6P-pkt: cannot get reserved; invalid argument\n");
return -1;
}
if((offset = get_reserved_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot get reserved; ");
PRINTF("packet [type=%u, code=%u] won't have Reserved\n",
type, code.value);
return -1;
}
/* The Reserved field is an 8-bit field */
memcpy(reserved, body + offset, sizeof(uint8_t));
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_set_offset(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_offset_t cell_offset,
uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(body == NULL) {
PRINTF("6P-pkt: cannot set offset; invalid argument\n");
return -1;
}
if((offset = get_offset_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot set offset; ");
PRINTF("packet [type=%u, code=%u] won't have Offset\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(cell_offset))) {
PRINTF("6P-pkt: cannot set offset; body is too short\n");
return -1;
}
/*
* The (Cell)Offset field is 16-bit long; treat it as a little-endian value of
* unsigned integer following IEEE 802.15.4-2015.
*/
(body + offset)[0] = *((uint16_t *)&cell_offset) & 0xff;
(body + offset)[1] = (*((uint16_t *)&cell_offset) >> 8) & 0xff;
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_get_offset(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_offset_t *cell_offset,
const uint8_t *body, uint16_t body_len)
{
int32_t offset;
const uint8_t *p;
if(cell_offset == NULL || body == NULL) {
PRINTF("6P-pkt: cannot get offset; invalid argument\n");
return -1;
}
if((offset = get_offset_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot get offset; ");
PRINTF("packet [type=%u, code=%u] won't have Offset\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(*cell_offset))) {
PRINTF("6P-pkt: cannot get offset; body is too short\n");
return -1;
}
/*
* The (Cell)Offset field is 16-bit long; treat it as a little-endian value of
* unsigned integer following IEEE 802.15.4-2015.
*/
p = body + offset;
*((uint16_t *)cell_offset) = p[0] + (p[1] << 8);
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_set_max_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_max_num_cells_t max_num_cells,
uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(body == NULL) {
PRINTF("6P-pkt: cannot set max_num_cells; invalid argument\n");
return -1;
}
if((offset = get_max_num_cells_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot set max_num_cells; ");
PRINTF("packet [type=%u, code=%u] won't have MaxNumCells\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(max_num_cells))) {
PRINTF("6P-pkt: cannot set max_num_cells; body is too short\n");
return -1;
}
/*
* The MaxNumCells field is 16-bit long; treat it as a little-endian value of
* unsigned integer following IEEE 802.15.4-2015.
*/
(body + offset)[0] = *((uint16_t *)&max_num_cells) & 0xff;
(body + offset)[1] = (*((uint16_t *)&max_num_cells) >> 8) & 0xff;
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_get_max_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_max_num_cells_t *max_num_cells,
const uint8_t *body, uint16_t body_len)
{
int32_t offset;
const uint8_t *p;
if(max_num_cells == NULL || body == NULL) {
PRINTF("6P-pkt: cannot get max_num_cells; invalid argument\n");
return -1;
}
if((offset = get_max_num_cells_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot get max_num_cells; ");
PRINTF("packet [type=%u, code=%u] won't have MaxNumCells\n",
type, code.value);
return -1;
}
if(body_len < (offset + sizeof(*max_num_cells))) {
PRINTF("6P-pkt: cannot get max_num_cells; body is too short\n");
return -1;
}
/*
* The MaxNumCells field is 16-bit long; treat it as a little-endian value of
* unsigned integer following IEEE 802.15.4-2015.
*/
p = body + offset;
*((uint16_t *)max_num_cells) = p[0] + (p[1] << 8);
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_set_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t *cell_list,
uint16_t cell_list_len,
uint16_t cell_offset,
uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(cell_list == NULL || body == NULL) {
PRINTF("6P-pkt: cannot set cell_list; invalid argument\n");
return -1;
}
if((offset = get_cell_list_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot set cell_list; ");
PRINTF("packet [type=%u, code=%u] won't have CellList\n",
type, code.value);
return -1;
}
offset += cell_offset * sizeof(sixp_pkt_cell_t);
if(body_len < (offset + cell_list_len)) {
PRINTF("6P-pkt: cannot set cell_list; body is too short\n");
return -1;
} else if((cell_list_len % sizeof(sixp_pkt_cell_t)) != 0) {
PRINTF("6P-pkt: cannot set cell_list; invalid {body, cell_list}_len\n");
return -1;
}
memcpy(body + offset, cell_list, cell_list_len);
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_get_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t **cell_list,
sixp_pkt_offset_t *cell_list_len,
const uint8_t *body, uint16_t body_len)
{
int32_t offset;
if(cell_list_len == NULL || body == NULL) {
PRINTF("6P-pkt: cannot get cell_list; invalid argument\n");
return -1;
}
if((offset = get_cell_list_offset(type, code)) < 0) {
PRINTF("6P-pkt: cannot get cell_list; ");
PRINTF("packet [type=%u, code=%u] won't have CellList\n",
type, code.value);
return -1;
}
if(body_len < offset) {
PRINTF("6P-pkt: cannot set cell_list; body is too short\n");
return -1;
} else if(((body_len - offset) % sizeof(sixp_pkt_cell_t)) != 0) {
PRINTF("6P-pkt: cannot set cell_list; invalid {body, cell_list}_len\n");
return -1;
}
if(cell_list != NULL) {
*cell_list = body + offset;
}
*cell_list_len = body_len - offset;
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_parse(const uint8_t *buf, uint16_t len,
sixp_pkt_t *pkt)
{
assert(buf != NULL && pkt != NULL);
if(buf == NULL || pkt == NULL) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of invalid argument\n");
return -1;
}
/* read the first 4 octets */
if(len < 4) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because it's a too short packet\n");
return -1;
}
if((buf[0] & 0x0f) != SIXP_PKT_VERSION) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of invalid version [%u]\n",
buf[0] & 0x0f);
return -1;
}
memset(pkt, 0, sizeof(sixp_pkt_t));
pkt->type = (buf[0] & 0x30) >> 4;
pkt->code.value = buf[1];
pkt->sfid = buf[2];
pkt->seqno = buf[3] & 0x0f;
pkt->gab = (buf[3] & 0x30) >> 4;
pkt->gba = (buf[3] & 0xc0) >> 6;
buf += 4;
len -= 4;
PRINTF("6P-pkt: sixp_pkt_parse() is processing [type:%u, code:%u, len:%u]\n",
pkt->type, pkt->code.value, len);
/* the rest is message body called "Other Fields" */
if(pkt->type == SIXP_PKT_TYPE_REQUEST) {
switch(pkt->code.cmd) {
case SIXP_PKT_CMD_ADD:
case SIXP_PKT_CMD_DELETE:
/* Add and Delete has the same request format */
if(len < (sizeof(sixp_pkt_metadata_t) +
sizeof(sixp_pkt_cell_options_t) +
sizeof(sixp_pkt_num_cells_t)) ||
(len % sizeof(uint32_t)) != 0) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of invalid length\n");
return -1;
}
break;
case SIXP_PKT_CMD_STATUS:
if(len != (sizeof(sixp_pkt_metadata_t) +
sizeof(sixp_pkt_cell_options_t))) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of invalid length\n");
return -1;
}
break;
case SIXP_PKT_CMD_LIST:
if(len != (sizeof(sixp_pkt_metadata_t) +
sizeof(sixp_pkt_cell_options_t) +
sizeof(sixp_pkt_reserved_t) +
sizeof(sixp_pkt_offset_t) +
sizeof(sixp_pkt_max_num_cells_t))) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of invalid length\n");
return -1;
}
break;
case SIXP_PKT_CMD_CLEAR:
if(len != sizeof(sixp_pkt_metadata_t)) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of invalid length\n");
return -1;
}
break;
default:
PRINTF("6P-pkt: sixp_pkt_parse() fails because of unsupported cmd\n");
return -1;
}
} else if(pkt->type == SIXP_PKT_TYPE_RESPONSE ||
pkt->type == SIXP_PKT_TYPE_CONFIRMATION) {
switch(pkt->code.rc) {
case SIXP_PKT_RC_SUCCESS:
/*
* The "Other Field" contains
* - Res to CLEAR: Empty (length 0)
* - Res to STATUS: "Num. Cells"
* - Res to ADD, DELETE, LIST: 0, 1, or multiple 6P cells
*/
if(len != 0 &&
len != sizeof(sixp_pkt_num_cells_t) &&
(len % sizeof(uint32_t)) != 0) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of invalid length\n");
return -1;
}
break;
case SIXP_PKT_RC_ERR_VER:
case SIXP_PKT_RC_ERR_SFID:
case SIXP_PKT_RC_ERR_GEN:
case SIXP_PKT_RC_ERR_BUSY:
case SIXP_PKT_RC_ERR_NORES:
case SIXP_PKT_RC_ERR_RESET:
case SIXP_PKT_RC_ERR:
if(len != 0) {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of invalid length\n");
return -1;
}
break;
default:
PRINTF("6P-pkt: sixp_pkt_parse() fails because of unsupported code\n");
return -1;
}
} else {
PRINTF("6P-pkt: sixp_pkt_parse() fails because of unsupported type\n");
return -1;
}
pkt->body = buf;
pkt->body_len = len;
return 0;
}
/*---------------------------------------------------------------------------*/
int
sixp_pkt_create(sixp_pkt_type_t type, sixp_pkt_code_t code,
uint8_t sfid, uint8_t seqno, uint8_t gab, uint8_t gba,
const uint8_t *body, uint16_t body_len, sixp_pkt_t *pkt)
{
uint8_t *hdr;
assert((body == NULL && body_len == 0) || (body != NULL && body_len > 0));
if((body == NULL && body_len > 0) || (body != NULL && body_len == 0)) {
PRINTF("6P-pkt: sixp_pkt_create() fails because of invalid argument\n");
return -1;
}
packetbuf_clear();
/*
* We're going to create a packet having 6top IE header (4 octets) and body
* (body_len octets).
*/
if(PACKETBUF_SIZE < (packetbuf_totlen() + body_len)) {
PRINTF("6P-pkt: sixp_pkt_create() fails because body is too long\n");
return -1;
}
if(packetbuf_hdralloc(4) != 1) {
PRINTF("6P-pkt: sixp_pkt_create fails to allocate header space\n");
return -1;
}
hdr = packetbuf_hdrptr();
/* header: write the 6top IE header, 4 octets */
hdr[0] = (type << 4) | SIXP_PKT_VERSION;
hdr[1] = code.value;
hdr[2] = sfid;
hdr[3] = (gab << 4) | (gba << 6) | seqno;
/* data: write body */
if(body_len > 0 && body != NULL) {
memcpy(packetbuf_dataptr(), body, body_len);
packetbuf_set_datalen(body_len);
}
/* copy information of a sending packet into pkt if necessary */
if(pkt != NULL) {
pkt->type = type;
pkt->code = code;
pkt->sfid = sfid;
pkt->seqno = seqno;
pkt->gab = gab;
pkt->gba = gba;
pkt->body = body;
pkt->body_len = body_len;
}
/* packetbuf is ready to be sent */
return 0;
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,443 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* 6top Protocol (6P) Packet Manipulation APIs
* \author
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#ifndef _SIXTOP_6P_PACKET_H_
#define _SIXTOP_6P_PACKET_H_
#define SIXP_PKT_VERSION 0x01
/* typedefs for code readability */
typedef uint8_t sixp_pkt_cell_options_t;
typedef uint8_t sixp_pkt_num_cells_t;
typedef uint8_t sixp_pkt_reserved_t;
typedef uint16_t sixp_pkt_metadata_t;
typedef uint16_t sixp_pkt_max_num_cells_t;
typedef uint16_t sixp_pkt_offset_t;
typedef uint32_t sixp_pkt_cell_t;
/**
* \brief 6P Message Types
*/
typedef enum {
SIXP_PKT_TYPE_REQUEST = 0x00, /**< 6P Request */
SIXP_PKT_TYPE_RESPONSE = 0x01, /**< 6P Response */
SIXP_PKT_TYPE_CONFIRMATION = 0x02, /**< 6P Confirmation */
SIXP_PKT_TYPE_RESERVED = 0x03, /**< Reserved */
} sixp_pkt_type_t;
/**
* \brief 6P Command Identifiers
*/
typedef enum {
SIXP_PKT_CMD_ADD = 0x01, /**< CMD_ADD */
SIXP_PKT_CMD_DELETE = 0x02, /**< CMD_DELETE */
SIXP_PKT_CMD_STATUS = 0x03, /**< CMD_STATUS */
SIXP_PKT_CMD_LIST = 0x04, /**< CMD_LIST */
SIXP_PKT_CMD_CLEAR = 0x05, /**< CMD_CLEAR */
SIXP_PKT_CMD_UNAVAILABLE /**< for internal use */
} sixp_pkt_cmd_t;
/**
* \brief 6P Return Codes
*/
typedef enum {
SIXP_PKT_RC_SUCCESS = 0x06, /**< RC_SUCCESS */
SIXP_PKT_RC_ERR_VER = 0x07, /**< RC_ERR_VER */
SIXP_PKT_RC_ERR_SFID = 0x08, /**< RC_ERR_SFID */
SIXP_PKT_RC_ERR_GEN = 0x09, /**< RC_ERR_GEN */
SIXP_PKT_RC_ERR_BUSY = 0x0a, /**< RC_ERR_BUSY */
SIXP_PKT_RC_ERR_NORES = 0x0b, /**< RC_ERR_NORES */
SIXP_PKT_RC_ERR_RESET = 0x0c, /**< RC_ERR_RESET */
SIXP_PKT_RC_ERR = 0x0d, /**< RC_ERR */
} sixp_pkt_rc_t;
/**
* \brief 6P Codes integrating Command IDs and Return Codes
*/
typedef union {
sixp_pkt_cmd_t cmd; /**< 6P Command Identifier */
sixp_pkt_rc_t rc; /**< 6P Return Code */
uint8_t value; /**< 8-bit unsigned integer value */
} sixp_pkt_code_t;
/**
* \brief 6P Cell Options
*/
typedef enum {
SIXP_PKT_CELL_OPTION_TX = 0x01, /**< TX Cell */
SIXP_PKT_CELL_OPTION_RX = 0x02, /**< RX Cell */
SIXP_PKT_CELL_OPTION_SHARED = 0x04 /**< SHARED Cell */
} sixp_pkt_cell_option_t;
/**
* \brief 6top IE Structure
*/
typedef struct {
sixp_pkt_type_t type; /**< Type */
sixp_pkt_code_t code; /**< Code */
uint8_t sfid; /**< SFID */
uint8_t seqno; /**< SeqNum */
uint8_t gab; /**< GAB */
uint8_t gba; /**< GBA */
const uint8_t *body; /**< Other Fields... */
uint16_t body_len; /**< The length of Other Fields */
} sixp_pkt_t;
/**
* \brief Write Metadata into "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param metadata Metadata to write
* \param body The pointer to "Other Fields" in a buffer
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_metadata(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_metadata_t metadata,
uint8_t *body, uint16_t body_len);
/**
* \brief Read Metadata stored in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param metadata The pointer to a buffer to store Metadata in
* \param body The pointer to the buffer having "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_metadata(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_metadata_t *metadata,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write CellOptions in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param cell_options "CellOptions" to write
* \param body The pointer to buffer having "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_cell_options(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_cell_options_t cell_options,
uint8_t *body, uint16_t body_len);
/**
* \brief Read CellOptions in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param cell_options The pointer to buffer to store CellOptions in
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_cell_options(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_cell_options_t *cell_options,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write NumCells in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param num_cells "NumCells" to write
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_num_cells_t num_cells,
uint8_t *body, uint16_t body_len);
/**
* \brief Read NumCells in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param num_cells The pointer to buffer to store NumCells in
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_num_cells_t *num_cells,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write Reserved in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param reserved "Reserved" to write
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_reserved(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_reserved_t reserved,
uint8_t *body, uint16_t body_len);
/**
* \brief Read Reserved in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param reserved The pointer to buffer to store Reserved in
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_reserved(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_reserved_t *reserved,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write Offset in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param offset "Offset" to write
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_offset(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_offset_t offset,
uint8_t *body, uint16_t body_len);
/**
* \brief Read Offset in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param offset The pointer to buffer to store Offset in
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_offset(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_offset_t *offset,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write MaxNumCells in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param max_num_cells "MaxNumCells" to write
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_max_num_cells(sixp_pkt_type_t type,
sixp_pkt_code_t code,
sixp_pkt_max_num_cells_t max_num_cells,
uint8_t *body, uint16_t body_len);
/**
* \brief Read MaxNumCells in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param max_num_cells The pointer to buffer to store MaxNumCells in
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_max_num_cells(sixp_pkt_type_t type,
sixp_pkt_code_t code,
sixp_pkt_max_num_cells_t *max_num_cells,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write CellList in "Other Fields" of 6P packet
* \note "offset" is specified by index in CellList
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param cell_list The pointer to "CellList" to write
* \param cell_list_len Length to write
* \param offset Offset in the "CellList" field to start writing
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t *cell_list,
uint16_t cell_list_len,
uint16_t offset,
uint8_t *body, uint16_t body_len);
/**
* \brief Read CellList in "Other Fields" of 6P packet
* \note If you want only the length of CellList, you can set null to cell_list.
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param cell_list The double pointer to store the starting address of CellList
* \param cell_list_len Pointer to store the length of CellList
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t **cell_list,
sixp_pkt_offset_t *cell_list_len,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write RelCellList in "Other Fields" of 6P packet
* \note "offset" is specified by index in RelCellList
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param rel_cell_list The pointer to "RelCellList" to write
* \param rel_cell_list_len Length to write
* \param offset Offset in the "RelCellList" field to start writing
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_rel_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t *rel_cell_list,
uint16_t rel_cell_list_len,
uint16_t offset,
uint8_t *body, uint16_t body_len);
/**
* \brief Read RelCellList in "Other Fields" of 6P packet
* \note If you want only the length of RelCellList, you can set null to
* rel_cell_list.
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param rel_cell_list The double pointer to store the starting address of
* RelCellList
* \param rel_cell_list_len Pointer to store the length of a returned
* RelCellList
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_rel_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t **rel_cell_list,
sixp_pkt_offset_t *rel_cell_list_len,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write CandCellList in "Other Fields" of 6P packet
* \note "offset" is specified by index in CandCellList
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param cand_cell_list The pointer to "CandCellList" to write
* \param cand_cell_list_len Length to write
* \param offset Offset in the "CandCellList" field to start writing
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_cand_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t *cand_cell_list,
uint16_t cand_cell_list_len,
uint16_t offset,
uint8_t *body, uint16_t body_len);
/**
* \brief Read CandCellList in "Other Fields" of 6P packet
* \note If you want only the length of CandCellList, you can set null to
* cell_list.
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param cand_cell_list The double pointer to store the starting address of
* CandCellList
* \param cand_cell_list_len Pointer to store the length of CandCellList
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_cand_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code,
const uint8_t **cand_cell_list,
sixp_pkt_offset_t *cand_cell_list_len,
const uint8_t *body, uint16_t body_len);
/**
* \brief Write TotalNumCells in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param total_num_cells "TotalNumCells" to write
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_set_total_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_total_num_cells_t total_num_cells,
uint8_t *body, uint16_t body_len);
/**
* \brief Read TotalNumCells in "Other Fields" of 6P packet
* \param type 6P Message Type
* \param code 6P Command Identifier or Return Code
* \param total_num_cells The pointer to buffer to store TotalNumCells in
* \param body The pointer to buffer pointing to "Other Fields"
* \param body_len The length of body, typically "Other Fields" length
* \return 0 on success, -1 on failure
*/
int sixp_pkt_get_total_num_cells(sixp_pkt_type_t type, sixp_pkt_code_t code,
sixp_pkt_total_num_cells_t *total_num_cells,
const uint8_t *body, uint16_t body_len);
/**
* \brief Parse a 6P packet
* \param buf The pointer to a buffer pointing 6top IE Content
* \param len The length of the buffer
* \param pkt The pointer to a sixp_pkt_t structure to store packet info
* \return 0 on success, -1 on failure
*/
int sixp_pkt_parse(const uint8_t *buf, uint16_t len,
sixp_pkt_t *pkt);
/**
* \brief Create a 6P packet
* \param type 6P Message Type
* \param code 6P Message Code, Command Identifier or Return Code
* \param sfid Scheduling Function Identifier
* \param seqno Sequence Number
* \param gab GAB
* \param gba GBA
* \param body The pointer to "Other Fields" in a buffer
* \param body_len The length of body, typically "Other Fields" length
* \param pkt The pointer to a sixp_pkt_t structure to store packet info
* (option)
* \return 0 on success, -1 on failure
*/
int sixp_pkt_create(sixp_pkt_type_t type, sixp_pkt_code_t code,
uint8_t sfid, uint8_t seqno, uint8_t gab, uint8_t gba,
const uint8_t *body, uint16_t body_len,
sixp_pkt_t *pkt);
#endif /* !_SIXP_PKT_H_ */
/** @} */

View File

@ -0,0 +1,388 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* Transaction Management for 6top Protocol (6P)
* \author
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#include "contiki-lib.h"
#include "lib/assert.h"
#include "sixtop.h"
#include "sixtop-conf.h"
#include "sixp-trans.h"
#define DEBUG DEBUG_PRINT
#include "net/net-debug.h"
/**
* \brief 6P Transaction Data Structure (for internal use)
*/
typedef struct sixp_trans {
struct sixp_trans *next;
const sixtop_sf_t *sf;
linkaddr_t peer_addr;
uint8_t seqno;
sixp_pkt_cmd_t cmd;
sixp_trans_state_t state;
sixp_trans_mode_t mode;
struct {
sixp_sent_callback_t func;
void *arg;
uint16_t arg_len;
} callback;
struct ctimer timer;
} sixp_trans_t;
static void handle_trans_timeout(void *ptr);
static void process_trans(void *ptr);
static void schedule_trans_process(sixp_trans_t *trans);
static void free_trans(sixp_trans_t *trans);
static sixp_trans_mode_t determine_trans_mode(const sixp_pkt_t *req);
MEMB(trans_memb, sixp_trans_t, SIXTOP_MAX_TRANSACTIONS);
LIST(trans_list);
/*---------------------------------------------------------------------------*/
static void
handle_trans_timeout(void *ptr)
{
sixp_trans_t *trans = (sixp_trans_t *)ptr;
assert(trans != NULL);
if(trans == NULL) {
return;
}
if(trans->sf->timeout != NULL) {
trans->sf->timeout(trans->cmd,
(const linkaddr_t *)&trans->peer_addr);
}
(void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
}
/*---------------------------------------------------------------------------*/
static void
process_trans(void *ptr)
{
sixp_trans_t *trans = (sixp_trans_t *)ptr;
assert(trans != NULL);
if(trans == NULL) {
return;
}
/* make sure that the timer is stopped */
ctimer_stop(&trans->timer);
/* state-specific operation */
if(trans->state == SIXP_TRANS_STATE_TERMINATING) {
/* handle the terminating state first */
PRINTF("6P-trans: trans [peer_addr:");
PRINTLLADDR((const uip_lladdr_t *)&trans->peer_addr);
PRINTF(", seqno:%u] is going to be freed\n", trans->seqno);
free_trans(trans);
return;
}
switch(trans->state) {
/* do for others */
case SIXP_TRANS_STATE_RESPONSE_SENT:
case SIXP_TRANS_STATE_RESPONSE_RECEIVED:
if(trans->mode == SIXP_TRANS_MODE_2_STEP) {
(void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
}
break;
case SIXP_TRANS_STATE_CONFIRMATION_SENT:
case SIXP_TRANS_STATE_CONFIRMATION_RECEIVED:
(void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
break;
case SIXP_TRANS_STATE_TERMINATING:
default:
break;
}
if(trans->state != SIXP_TRANS_STATE_TERMINATING) {
/* set the timer with a timeout values defined by the SF */
ctimer_set(&trans->timer, trans->sf->timeout_interval,
handle_trans_timeout, trans);
}
}
/*---------------------------------------------------------------------------*/
static void
schedule_trans_process(sixp_trans_t *trans)
{
assert(trans != NULL);
if(trans == NULL) {
return;
}
ctimer_stop(&trans->timer);
ctimer_set(&trans->timer, 0, process_trans, trans); /* expires immediately */
}
/*---------------------------------------------------------------------------*/
static void
free_trans(sixp_trans_t *trans)
{
assert(trans != NULL);
if(trans == NULL) {
return;
}
list_remove(trans_list, trans);
memb_free(&trans_memb, trans);
}
/*---------------------------------------------------------------------------*/
static sixp_trans_mode_t
determine_trans_mode(const sixp_pkt_t *req)
{
uint16_t cell_list_len;
assert(req != NULL);
if(req == NULL) {
return SIXP_TRANS_MODE_UNAVAILABLE;
}
/*
* We consider a transaction as 3-step if and only if its request command is
* either Add or Delete AND its cell_list is empty. Otherwise, 2-step.
*/
if(req->type == SIXP_PKT_TYPE_REQUEST &&
(req->code.cmd == SIXP_PKT_CMD_ADD ||
req->code.cmd == SIXP_PKT_CMD_DELETE) &&
sixp_pkt_get_cell_list(req->type, (sixp_pkt_code_t)req->code.value,
NULL, &cell_list_len,
req->body, req->body_len) == 0 &&
cell_list_len == 0) {
return SIXP_TRANS_MODE_3_STEP;
}
return SIXP_TRANS_MODE_2_STEP;
}
/*---------------------------------------------------------------------------*/
int
sixp_trans_transit_state(sixp_trans_t *trans, sixp_trans_state_t new_state)
{
assert(trans != NULL);
if(trans == NULL) {
PRINTF("6top: invalid argument, trans is NULL\n");
return -1;
}
/* enforce state transition rules */
if(new_state == SIXP_TRANS_STATE_TERMINATING ||
(new_state == SIXP_TRANS_STATE_REQUEST_SENT &&
trans->state == SIXP_TRANS_STATE_INIT) ||
(new_state == SIXP_TRANS_STATE_REQUEST_RECEIVED &&
trans->state == SIXP_TRANS_STATE_INIT) ||
(new_state == SIXP_TRANS_STATE_RESPONSE_SENT &&
trans->state == SIXP_TRANS_STATE_REQUEST_RECEIVED) ||
(new_state == SIXP_TRANS_STATE_RESPONSE_RECEIVED &&
trans->state == SIXP_TRANS_STATE_REQUEST_SENT) ||
(new_state == SIXP_TRANS_STATE_CONFIRMATION_RECEIVED &&
trans->state == SIXP_TRANS_STATE_RESPONSE_SENT &&
trans->mode == SIXP_TRANS_MODE_3_STEP) ||
(new_state == SIXP_TRANS_STATE_CONFIRMATION_SENT &&
trans->state == SIXP_TRANS_STATE_RESPONSE_RECEIVED &&
trans->mode == SIXP_TRANS_MODE_3_STEP)) {
PRINTF("6P-trans: trans %p state changes from %u to %u\n",
trans, trans->state, new_state);
trans->state = new_state;
schedule_trans_process(trans);
return 0;
}
/* invalid transition */
PRINTF("6P-trans: invalid transaction, from %u to %u, detected on trans %p\n",
trans->state, new_state, trans);
return -1;
}
/*---------------------------------------------------------------------------*/
sixp_pkt_cmd_t
sixp_trans_get_cmd(sixp_trans_t *trans)
{
assert(trans != NULL);
if(trans == NULL) {
return SIXP_PKT_CMD_UNAVAILABLE;
}
return trans->cmd;
}
/*---------------------------------------------------------------------------*/
sixp_trans_state_t
sixp_trans_get_state(sixp_trans_t *trans)
{
assert(trans != NULL);
if(trans == NULL) {
return SIXP_TRANS_STATE_UNAVAILABLE;
}
return trans->state;
}
/*---------------------------------------------------------------------------*/
int16_t
sixp_trans_get_seqno(sixp_trans_t *trans)
{
assert(trans != NULL);
if(trans == NULL) {
PRINTF("6P-trans: sixp_trans_get_seqno() fails because trans is NULL\n");
return -1;
}
return trans->seqno;
}
/*---------------------------------------------------------------------------*/
sixp_trans_mode_t
sixp_trans_get_mode(sixp_trans_t *trans)
{
assert(trans != NULL);
if(trans == NULL) {
PRINTF("6P-trans: sixp_trans_get_mode() fails because trans is NULL\n");
return SIXP_TRANS_STATE_UNAVAILABLE;
}
return trans->mode;
}
/*---------------------------------------------------------------------------*/
void
sixp_trans_invoke_callback(sixp_trans_t *trans, sixp_output_status_t status)
{
assert(trans != NULL);
if(trans == NULL || trans->callback.func == NULL) {
return;
}
trans->callback.func(trans->callback.arg, trans->callback.arg_len,
&trans->peer_addr, status);
}
/*---------------------------------------------------------------------------*/
void
sixp_trans_set_callback(sixp_trans_t *trans,
sixp_sent_callback_t func, void *arg, uint16_t arg_len)
{
assert(trans != NULL);
if(trans == NULL) {
return;
}
trans->callback.func = func;
trans->callback.arg = arg;
trans->callback.arg_len = arg_len;
}
/*---------------------------------------------------------------------------*/
sixp_trans_t *
sixp_trans_alloc(const sixp_pkt_t *pkt, const linkaddr_t *peer_addr)
{
const sixtop_sf_t *sf;
sixp_trans_t *trans;
assert(pkt != NULL && peer_addr != NULL);
if(pkt == NULL || peer_addr == NULL) {
PRINTF("6P-trans: sixp_trans_alloc() fails because of invalid argument\n");
return NULL;
}
if((sf = sixtop_find_sf(pkt->sfid)) == NULL) {
PRINTF("6P-trans: sixp_trans_alloc() fails; no suitable SF [sfid:%u]\n",
pkt->sfid);
return NULL;
}
if(sixp_trans_find(peer_addr) != NULL) {
PRINTF("6P-trans: sixp_trans_alloc() fails because another trans with ");
PRINTLLADDR((const uip_lladdr_t *)peer_addr);
PRINTF("is in process\n");
return NULL;
}
if((trans = memb_alloc(&trans_memb)) == NULL) {
PRINTF("6P-trans: sixp_trans_alloc() fails because of lack of memory\n");
return NULL;
}
memset(trans, 0, sizeof(sixp_trans_t));
trans->sf = sf;
trans->peer_addr = *peer_addr;
trans->seqno = pkt->seqno;
trans->cmd = pkt->code.value;
trans->state = SIXP_TRANS_STATE_INIT;
trans->mode = determine_trans_mode(pkt);
list_add(trans_list, trans);
return trans;
}
/*---------------------------------------------------------------------------*/
sixp_trans_t *
sixp_trans_find(const linkaddr_t *peer_addr)
{
sixp_trans_t *trans;
assert(peer_addr != NULL);
if(peer_addr == NULL) {
return NULL;
}
/*
* XXX: we don't support concurrent 6P transactions which is mentioned in
* Section 4.3.3, draft-ietf-6tisch-6top-protocol-03.
*
* The assumption here is that there is one transactions for a single peer at
* most.
*/
for(trans = list_head(trans_list);
trans != NULL; trans = trans->next) {
if(memcmp(peer_addr, &trans->peer_addr, sizeof(linkaddr_t)) == 0) {
return trans;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
int
sixp_trans_init(void)
{
sixp_trans_t *trans, *next_trans;
/* make sure there's no timer task left before the initialization */
for(trans = list_head(trans_list);
trans != NULL; trans = next_trans) {
next_trans = trans->next;
ctimer_stop(&trans->timer);
free_trans(trans);
}
list_init(trans_list);
memb_init(&trans_memb);
return 0;
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,151 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* Transaction Management APIs for 6top Protocol (6P)
* \author
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#include "sixp.h"
#include "sixp-pkt.h"
/**
* \brief 6P Transaction States (for internal use)
*/
typedef enum {
SIXP_TRANS_STATE_UNAVAILABLE = 0,
SIXP_TRANS_STATE_INIT,
SIXP_TRANS_STATE_REQUEST_SENT,
SIXP_TRANS_STATE_REQUEST_RECEIVED,
SIXP_TRANS_STATE_RESPONSE_SENT,
SIXP_TRANS_STATE_RESPONSE_RECEIVED,
SIXP_TRANS_STATE_CONFIRMATION_SENT,
SIXP_TRANS_STATE_CONFIRMATION_RECEIVED,
SIXP_TRANS_STATE_TERMINATING,
} sixp_trans_state_t;
/**
* \brief 6P Transaction Modes (for internal use)
*/
typedef enum {
SIXP_TRANS_MODE_UNAVAILABLE = 0,
SIXP_TRANS_MODE_2_STEP,
SIXP_TRANS_MODE_3_STEP
} sixp_trans_mode_t;
typedef struct sixp_trans sixp_trans_t;
/**
* \brief Change the state of a specified transaction
* \param trans The pointer to a transaction
* \param new_state New state to move the transaction to
* \return 0 on success, -1 on failure
*/
int sixp_trans_transit_state(sixp_trans_t *trans,
sixp_trans_state_t new_state);
/**
* \brief Return the command associated with a specified transaction
* \param trans The pointer to a transaction
* \return Command identifier; SIXP_PKT_CMD_UNAVAILABLE on failure
*/
sixp_pkt_cmd_t sixp_trans_get_cmd(sixp_trans_t *trans);
/**
* \brief Return the state of a specified transaction
* \param trans The pointer to a transaction
* \return a state of the transaction; SIXP_TRANS_STATE_UNAVAILABLE if the
* transaction is not found in the system.
*/
sixp_trans_state_t sixp_trans_get_state(sixp_trans_t *trans);
/**
* \brief Return the sequence number associated with a specified transaction
* \param trans The pointer of a transaction
* \return 0 or larger than 0 on success, -1 on failure
*/
int16_t sixp_trans_get_seqno(sixp_trans_t *trans);
/**
* \brief Return the mode, 2-step or 3-step, of a specified transaction
* \param trans The pointer to a transaction
* \return The mode of the transaction, SIXP_TRANS_MODE_UNAVAILABLE on failure
*/
sixp_trans_mode_t sixp_trans_get_mode(sixp_trans_t *trans);
/**
* \brief Invoke the output callback of a specified transaction
* \param trans The pointer to a transaction
* \param status An output result value
*/
void sixp_trans_invoke_callback(sixp_trans_t *trans,
sixp_output_status_t status);
/**
* \brief Set an output callback to a specified transaction
* \param trans The pointer to a transaction
* \param func The pointer to a callback function
* \param arg The pointer to an argument which will be passed to func
* \param arg_len The length of the argument
*/
void sixp_trans_set_callback(sixp_trans_t *trans,
sixp_sent_callback_t func,
void *arg,
uint16_t arg_len);
/**
* \brief Allocate a transaction
* \param pkt The pointer to a packet which triggers the allocation
* \param peer_addr The peer address which will be associated
* \return A pointer to an newly allocated transaction, NULL on failure
*/
sixp_trans_t *sixp_trans_alloc(const sixp_pkt_t *pkt,
const linkaddr_t *peer_addr);
/**
* \brief Find a transaction
* \param peer_addr The peer address
* \return The pointer to a transaction; NULL on failure
*/
sixp_trans_t *sixp_trans_find(const linkaddr_t *peer_addr);
/**
* \brief Initialize Memory and List for 6P transactions
* This function removes and frees existing transactions.
*/
int sixp_trans_init(void);
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,437 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* 6top Protocol (6P)
* \author
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#include "contiki-lib.h"
#include "lib/assert.h"
#include "sixtop.h"
#include "sixp-nbr.h"
#include "sixp-pkt.h"
#include "sixp-trans.h"
#define DEBUG DEBUG_PRINT
#include "net/net-debug.h"
static void mac_callback(void *ptr, int status, int transmissions);
static int send_back_error(sixp_pkt_type_t type, sixp_pkt_code_t code,
uint8_t sfid, uint8_t seqno,
const linkaddr_t *dest_addr);
/*---------------------------------------------------------------------------*/
static void
mac_callback(void *ptr, int status, int transmissions)
{
sixp_trans_t *trans = (sixp_trans_t *)ptr;
sixp_trans_state_t new_state, current_state;
assert(trans != NULL);
if(trans == NULL) {
PRINTF("6P: mac_callback() fails because trans is NULL\n");
return;
}
current_state = sixp_trans_get_state(trans);
if(status == MAC_TX_OK) {
switch(current_state) {
case SIXP_TRANS_STATE_INIT:
new_state = SIXP_TRANS_STATE_REQUEST_SENT;
break;
case SIXP_TRANS_STATE_REQUEST_RECEIVED:
new_state = SIXP_TRANS_STATE_RESPONSE_SENT;
break;
case SIXP_TRANS_STATE_RESPONSE_RECEIVED:
new_state = SIXP_TRANS_STATE_CONFIRMATION_SENT;
break;
default:
PRINTF("6P: mac_callback() fails because of an unexpected state (%u)\n",
current_state);
return;
}
} else {
/*
* In a case of transmission failure of a request, a corresponding SF would
* retransmit the request with a new transaction. For a response or a
* confirmation, the same transaction will be used for retransmission as
* long as it doesn't have timeout.
*/
if(current_state == SIXP_TRANS_STATE_INIT) {
/* request case */
new_state = SIXP_TRANS_STATE_TERMINATING;
} else {
/* response or confirmation case: stay the same state */
new_state = current_state;
}
}
if(new_state != current_state &&
sixp_trans_transit_state(trans, new_state) != 0) {
PRINTF("6P: mac_callback() fails because of state transition failure\n");
PRINTF("6P: something wrong; we're terminating the trans %p\n", trans);
(void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
return;
}
sixp_trans_invoke_callback(trans,
status == MAC_TX_OK ?
SIXP_OUTPUT_STATUS_SUCCESS :
SIXP_OUTPUT_STATUS_FAILURE);
sixp_trans_set_callback(trans, NULL, NULL, 0);
}
/*---------------------------------------------------------------------------*/
static int
send_back_error(sixp_pkt_type_t type, sixp_pkt_code_t code,
uint8_t sfid, uint8_t seqno,
const linkaddr_t *dest_addr)
{
/* create a 6P packet within packetbuf */
/* XXX: set 0 as GAB and GBA for a error response */
/* XXX: how can we make a confirmation having an error return value? */
if(sixp_pkt_create(type, code, sfid, seqno, 0, 0, NULL, 0, NULL) < 0) {
PRINTF("6P: failed to create a 6P packet to return an error [rc:%u]\n",
code.value);
return -1;
}
/* we don't care about how the transmission goes; no need to set callback */
sixtop_output(dest_addr, NULL, NULL);
return 0;
}
/*---------------------------------------------------------------------------*/
void
sixp_input(const uint8_t *buf, uint16_t len, const linkaddr_t *src_addr)
{
sixp_pkt_t pkt;
sixp_nbr_t *nbr;
uint8_t invalid_schedule_generation;
sixp_trans_t *trans;
const sixtop_sf_t *sf;
int16_t seqno;
int ret;
assert(buf != NULL && src_addr != NULL);
if(buf == NULL || src_addr == NULL) {
return;
}
if(sixp_pkt_parse(buf, len, &pkt) < 0) {
PRINTF("6P: sixp_input() fails because off a malformed 6P packet\n");
return;
}
if(pkt.type != SIXP_PKT_TYPE_REQUEST &&
pkt.type != SIXP_PKT_TYPE_RESPONSE &&
pkt.type != SIXP_PKT_TYPE_CONFIRMATION) {
PRINTF("6P: sixp_input() fails because of unsupported type [type:%u]\n",
pkt.type);
return;
}
if((sf = sixtop_find_sf(pkt.sfid)) == NULL) {
PRINTF("6P: sixp_input() fails because SF [sfid:%u] is unavailable\n",
pkt.sfid);
/*
* XXX: what if the incoming packet is a response? confirmation should be
* sent back?
*/
if(send_back_error(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_SFID,
pkt.sfid, pkt.seqno, src_addr) < 0) {
PRINTF("6P: sixp_input() fails to return an error response\n");
};
return;
}
nbr = sixp_nbr_find(src_addr);
/* Generation Management */
if(pkt.code.value == SIXP_PKT_CMD_CLEAR) {
/* Not need to validate generation counters in a case of CMD_CLEAR */
invalid_schedule_generation = 0;
} else if(nbr == NULL) {
if(pkt.gab == 0 && pkt.gba == 0) {
invalid_schedule_generation = 0; /* valid combination */
} else {
PRINTF("6P: GAB/GBA should be 0 because of no corresponding nbr\n");
invalid_schedule_generation = 1;
}
} else {
PRINTF("6P: GAB: %u, GBA: %u, GTX: %u, GRX: %u\n",
pkt.gab, pkt.gba, sixp_nbr_get_grx(nbr), sixp_nbr_get_gtx(nbr));
if(((pkt.type == SIXP_PKT_TYPE_REQUEST ||
pkt.type == SIXP_PKT_TYPE_CONFIRMATION) &&
pkt.gab == sixp_nbr_get_grx(nbr) &&
pkt.gba == sixp_nbr_get_gtx(nbr)) ||
(pkt.type == SIXP_PKT_TYPE_RESPONSE &&
pkt.gab == sixp_nbr_get_gtx(nbr) &&
pkt.gba == sixp_nbr_get_grx(nbr))) {
invalid_schedule_generation = 0; /* valid combination */
} else {
invalid_schedule_generation = 1;
}
}
if(invalid_schedule_generation) {
PRINTF("6P: sixp_input() fails because of schedule generation mismatch\n");
return;
}
/* Transaction Management */
trans = sixp_trans_find(src_addr);
if(pkt.type == SIXP_PKT_TYPE_REQUEST) {
if(trans != NULL) {
/* Error: not supposed to have another transaction with the peer. */
PRINTF("6P: sixp_input() fails because another request [peer_addr:");
PRINTLLADDR((const uip_lladdr_t *)src_addr);
PRINTF(" seqno:%u] is in process\n", sixp_trans_get_seqno(trans));
if(send_back_error(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_BUSY,
pkt.sfid, pkt.seqno, src_addr) < 0) {
PRINTF("6P: sixp_input() fails to return an error response");
}
return;
} else if((trans = sixp_trans_alloc(&pkt, src_addr)) == NULL) {
PRINTF("6P: sixp_input() fails because of lack of memory\n");
if(send_back_error(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_ERR_NORES,
pkt.sfid, pkt.seqno, src_addr) < 0) {
PRINTF("6P: sixp_input() fails to return an error response\n");
}
return;
}
} else if(pkt.type == SIXP_PKT_TYPE_RESPONSE ||
pkt.type == SIXP_PKT_TYPE_CONFIRMATION) {
if(trans == NULL) {
/* Error: should have a transaction for incoming packet */
PRINTF("6P: sixp_input() fails because of no trans [peer_addr:");
PRINTLLADDR((const uip_lladdr_t *)src_addr);
PRINTF("]\n");
return;
} else if((seqno = sixp_trans_get_seqno(trans)) < 0 ||
seqno != pkt.seqno) {
PRINTF("6P: sixp_input() fails because of invalid seqno [seqno:%u, %u]\n",
seqno, pkt.seqno);
return;
}
}
/* state transition */
assert(trans != NULL);
switch(pkt.type) {
case SIXP_PKT_TYPE_REQUEST:
ret = sixp_trans_transit_state(trans,
SIXP_TRANS_STATE_REQUEST_RECEIVED);
break;
case SIXP_PKT_TYPE_RESPONSE:
ret = sixp_trans_transit_state(trans,
SIXP_TRANS_STATE_RESPONSE_RECEIVED);
break;
case SIXP_PKT_TYPE_CONFIRMATION:
ret = sixp_trans_transit_state(trans,
SIXP_TRANS_STATE_CONFIRMATION_RECEIVED);
break;
default:
PRINTF("6P: sixp_input() fails because of unsupported type [type:%u]\n",
pkt.type);
return;
}
if(ret < 0) {
PRINTF("6P: sixp_input() fails because of state transition failure\n");
PRINTF("6P: something wrong; we're terminating the trans %p\n", trans);
(void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
return;
}
if(sf->input != NULL) {
sf->input(pkt.type, pkt.code, pkt.body, pkt.body_len, src_addr);
}
return;
}
/*---------------------------------------------------------------------------*/
int
sixp_output(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid,
const uint8_t *body, uint16_t body_len,
const linkaddr_t *dest_addr,
sixp_sent_callback_t func, void *arg, uint16_t arg_len)
{
sixp_trans_t *trans;
sixp_nbr_t *nbr;
sixp_pkt_cmd_t cmd;
int16_t seqno, gab, gba;
sixp_pkt_t pkt;
assert(dest_addr != NULL);
/* validate the state of a transaction with a specified peer */
trans = sixp_trans_find(dest_addr);
if(type == SIXP_PKT_TYPE_REQUEST) {
if(trans != NULL) {
PRINTF("6P: sixp_output() fails because another trans for [peer_addr:");
PRINTLLADDR((const uip_lladdr_t *)dest_addr);
PRINTF("] is in process\n");
return -1;
} else {
/* ready to send a request */
/* we're going to allocate a new transaction later */
}
} else if(type == SIXP_PKT_TYPE_RESPONSE) {
if(trans == NULL) {
PRINTF("6P: sixp_output() fails because of no transaction [peer_addr:");
PRINTLLADDR((const uip_lladdr_t *)dest_addr);
PRINTF("]\n");
return -1;
} else if(sixp_trans_get_state(trans) !=
SIXP_TRANS_STATE_REQUEST_RECEIVED) {
PRINTF("6P: sixp_output() fails because of invalid transaction state\n");
return -1;
} else {
/* ready to send a response */
}
} else if(type == SIXP_PKT_TYPE_CONFIRMATION) {
if(trans == NULL) {
PRINTF("6P: sixp_output() fails because of no transaction [peer_addr:\n");
PRINTLLADDR((const uip_lladdr_t *)dest_addr);
PRINTF("\n");
return -1;
} else if(sixp_trans_get_state(trans) !=
SIXP_TRANS_STATE_RESPONSE_RECEIVED) {
PRINTF("6P: sixp_output() fails because of invalid transaction state\n");
return -1;
} else {
/* ready to send a confirmation */
}
} else {
PRINTF("6P: sixp_output() fails because of unsupported type [type:%u]\n",
type);
return -1;
}
nbr = sixp_nbr_find(dest_addr);
/*
* Make sure we have a nbr for the peer if the packet is a response with
* success so that we can manage the schedule generation.
*/
if(nbr == NULL &&
type == SIXP_PKT_TYPE_RESPONSE && code.value == SIXP_PKT_RC_SUCCESS &&
((cmd = sixp_trans_get_cmd(trans)) == SIXP_PKT_CMD_ADD ||
cmd == SIXP_PKT_CMD_DELETE) &&
(nbr = sixp_nbr_alloc(dest_addr)) == NULL) {
PRINTF("6P: sixp_output() fails because of no memory for another nbr\n");
return -1;
}
/* set SeqNum */
if(type == SIXP_PKT_TYPE_REQUEST) {
if(nbr == NULL &&
(nbr = sixp_nbr_alloc(dest_addr)) == NULL) {
PRINTF("6P: sixp_output() fails because it fails to allocate a nbr\n");
return -1;
}
if((seqno = sixp_nbr_get_next_seqno(nbr)) < 0){
PRINTF("6P: sixp_output() fails to get the next sequence number\n");
return -1;
}
if(sixp_nbr_increment_next_seqno(nbr) < 0) {
PRINTF("6P: sixp_output() fails to increment the next sequence number\n");
return -1;
}
} else {
assert(trans != NULL);
if((seqno = sixp_trans_get_seqno(trans)) < 0) {
PRINTF("6P: sixp_output() fails because it fails to get seqno\n");
return -1;
}
}
/* set GAB and GBA */
if(nbr == NULL) {
gab = gba = 0;
} else {
if(type == SIXP_PKT_TYPE_REQUEST ||
type == SIXP_PKT_TYPE_CONFIRMATION) {
gab = sixp_nbr_get_gtx(nbr);
gba = sixp_nbr_get_grx(nbr);
} else if(type == SIXP_PKT_TYPE_RESPONSE) {
gba = sixp_nbr_get_gtx(nbr);
gab = sixp_nbr_get_grx(nbr);
} else {
/* never come here */
PRINTF("6P: sixp_output() fails because of an unexpected condition\n");
return -1;
}
}
if(gab < 0 || gba < 0) {
PRINTF("6P: sixp_output() fails to get GAB or GBA\n");
return -1;
}
/* create a 6P packet within packetbuf */
if(sixp_pkt_create(type, code, sfid,
(uint8_t)seqno, (uint8_t)gab, (uint8_t)gba,
body, body_len,
type == SIXP_PKT_TYPE_REQUEST ? &pkt : NULL) < 0) {
PRINTF("6P: sixp_output() fails to create a 6P packet\n");
return -1;
}
/* allocate a transaction for a sending request */
if(type == SIXP_PKT_TYPE_REQUEST) {
assert(trans == NULL);
if((trans = sixp_trans_alloc(&pkt, dest_addr)) == NULL) {
PRINTF("6P: sixp_output() is aborted because of no memory\n");
return -1;
} else {
/* ready for proceed */
}
}
assert(trans != NULL);
sixp_trans_set_callback(trans, func, arg, arg_len);
sixtop_output(dest_addr, mac_callback, trans);
return 0;
}
/*---------------------------------------------------------------------------*/
void
sixp_init(void)
{
sixp_nbr_init();
sixp_trans_init();
}
/*---------------------------------------------------------------------------*/
/** @} */

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* 6top Protocol (6P) APIs
* \author
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#ifndef _SIXP_H_
#define _SIXP_H_
#include "net/linkaddr.h"
#include "sys/clock.h"
#include "sixp-pkt.h"
#define SIXP_SUBIE_ID 0x00
#ifdef SIXP_CONF_WITH_PAYLOAD_TERMINATION_IE
#define SIXP_WITH_PAYLOAD_TERMINATION_IE SIXP_CONF_WITH_PAYLOAD_TERMINATION_IE
#else
#define SIXP_WITH_PAYLOAD_TERMINATION_IE 0
#endif /* SIXP_CONF_WITH_PAYLOAD_TERMINATION_IE */
/**
* \brief The initial sequence number used for 6P request
*/
#define SIXP_INITIAL_SEQUENCE_NUMBER 0
/**
* \brief 6P Send Status, which represents sixp_output() result.
*/
typedef enum {
SIXP_OUTPUT_STATUS_SUCCESS, /**< SUCCESS */
SIXP_OUTPUT_STATUS_FAILURE /**< FAILURE */
} sixp_output_status_t;
/**
* \brief 6P Packet Sent Handler
*/
typedef void (*sixp_sent_callback_t)(void *arg, uint16_t arg_len,
const linkaddr_t *dest_addr,
sixp_output_status_t status);
/**
* \brief Input a 6P packet
* \param buf The pointer to a buffer pointing the head of 6top IE Content
* \param len The lengh of 6top IE Content
* \param src_addr The Source address of an incoming packet
* \return 0 if , -1 on failure
*/
void sixp_input(const uint8_t *buf, uint16_t len,
const linkaddr_t *src_addr);
/**
* \brief Output a 6P packet
* \param type Message Type
* \param code Message Code; Command ID or Return Code
* \param sfid Scheduling Function Identifier
* \param body 6top IE Content
* \param body_len The length of 6top IE Content
* \param dest_addr The destination Address
* \param func callback function invoked after the transmission process
* \param arg The pointer to an argument to be passed with the callback
* \param arg_len The length of the argument
* \return 0 on success, -1 on failure
*/
int sixp_output(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid,
const uint8_t *body, uint16_t body_len,
const linkaddr_t *dest_addr,
sixp_sent_callback_t func, void *arg, uint16_t arg_len);
/**
* \brief Initialize 6P Module
* It invokes sixp_nbr_init() and sixp_trans_init().
*/
void sixp_init(void);
#endif /* ! _SIXP_H_ */
/** @} */

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2016, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup sixtop
* @{
*/
/**
* \file
* 6top Configuration
* \author
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#ifndef __SIXTOP_CONF_H__
#define __SIXTOP_CONF_H__
/**
* \brief The maximum number of Scheduling Functions in the system.
*/
#ifdef SIXTOP_CONF_MAX_SCHEDULING_FUNCTIONS
#define SIXTOP_MAX_SCHEDULING_FUNCTIONS SIXTOP_CONF_MAX_SCHEDULING_FUNCTIONS
#else
#define SIXTOP_MAX_SCHEDULING_FUNCTIONS 1
#endif
/**
* \brief The maximum number of transactions which the sixtop module can handle
* at the same time.
*/
#ifdef SIXTOP_CONF_MAX_TRANSACTIONS
#define SIXTOP_MAX_TRANSACTIONS SIXTOP_CONF_MAX_TRANSACTIONS
#else
#define SIXTOP_MAX_TRANSACTIONS 1
#endif
#endif /* !__SIXTOP_CONF_H__ */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Swedish Institute of Computer Science.
* Copyright (c) 2016, Yasuyuki Tanaka
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -10,96 +10,132 @@
* 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.
* 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
/**
* \addtogroup net
* @{
*/
/**
* \defgroup sixtop 6TiSCH Operation Sublayer (6top)
* @{
*/
/**
* \file
* A sixtop protocol that performs link addition/deletion
* 6TiSCH Operation Sublayer (6top) APIs
* \author
* Shalu R <shalur@cdac.in>
* Lijo Thomas <lijo@cdac.in>
* Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
*/
#ifndef __SIXTOP_H__
#define __SIXTOP_H__
#ifndef _SIXTOP_H_
#define _SIXTOP_H_
#include "contiki.h"
#include "stdbool.h"
#include "net/ip/uip-debug.h"
#include "net/mac/mac.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
#include "sixp-pkt.h"
/* Link Option OFF */
#define LINK_OPTION_OFF 0
/**
* \brief Input Handler of Scheduling Function
* \param type 6P Message Type of an input packet
* \param code Code, 6P Command Identifier or Return Code, of an input packet
* \param body Body, "Other Fields", of an input packet
* \param body_len The length of body
* \param body src_addr Source address of an input packet
*/
typedef void (* sixtop_sf_input)(sixp_pkt_type_t type,
sixp_pkt_code_t code,
const uint8_t *body,
uint16_t body_len,
const linkaddr_t *src_addr);
/* Maximum number of retransmissions permissible at MAC layer */
#define SIXTOP_CONF_MAX_MAC_TRANSMISSIONS 3
/**
* \brief Timeout Handler of Scheduling Function
* \param cmd 6P Command (Identifier) in process under the transaction
* \param peer_addr The peer address of the transaction
*/
typedef void (* sixtop_sf_timeout)(sixp_pkt_cmd_t cmd,
const linkaddr_t *peer_addr);
/**
* /brief Scheduling Function Driver
*/
typedef struct {
uint8_t sfid; /**< SFID */
clock_time_t timeout_interval; /**< Timeout Value */
void (*init)(void); /**< Init Function */
sixtop_sf_input input; /**< Input Handler */
sixtop_sf_timeout timeout; /**< Transaction Timeout Handler */
} sixtop_sf_t;
/**
* \var sixtop_sf_t::sfid
* managed: 0x00-0xfe
* unmanaged: 0xf0-0xfe
* reserved: 0xff
*/
/* 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 */
};
/**
* \brief Add a Scheduling Function (SF) to 6top Sublayer
* \param sf The pointer to a Scheduling Function Driver
* \return 0 on success, -1 on failure
*
* If there is a SF whose SF is identical to one of a SF specified to this API,
* the addition will fail and -1 will be returned. If there is no room to
* another SF, -1 will be returned as well. You can specify how many SFs can be
* added with SIXTOP_CONF_MAX_SCHEDULING_FUNCTIONS.
*/
int sixtop_add_sf(const sixtop_sf_t *sf);
/* 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;
/**
* \brief Find a SF which has been added by SFID
* \param sfid Scheduling Function Identifier of a SF
* \return The pointer to a SF driver having the specified SFID on success, NULL
* on failure (not found)
*/
const sixtop_sf_t *sixtop_find_sf(uint8_t sfid);
/********** 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);
/**
* \brief Output a 6P packet which is supposestored in packetbuf
* \param dest_addr Destination address of the outgoing packet
* \param callback MAC callback function to get a TX result
* \param arg The pointer to an argument which is returned with the MAC callback
*/
void sixtop_output(const linkaddr_t *dest_addr,
mac_callback_t callback, void *arg);
#endif /* __SIXTOP_H__ */
/**
* \brief Input a packet stored in packetbuf
*/
void sixtop_input(void);
/**
* \brief Initialize 6top module
* This initialization function removes all the SFs which has been installed
* into the 6top sub-layer. In addition, it invokes sixp_init().
*/
void sixtop_init(void);
/**
* \brief Initialize installed SFs which has been added in the system
* This function is supposed to be invoked every time the node gets associated.
*/
void sixtop_init_sf(void);
#endif /* !_SIXTOP_H_ */
/** @} */
/** @} */

View File

@ -55,7 +55,6 @@
#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"
@ -63,6 +62,10 @@
#include "net/mac/tsch/tsch-rpl.h"
#endif /* UIP_CONF_IPV6_RPL */
#if TSCH_WITH_SIXTOP
#include "net/mac/tsch/sixtop/sixtop.h"
#endif
#if FRAME802154_VERSION < FRAME802154_IEEE802154_2015
#error TSCH: FRAME802154_VERSION must be at least FRAME802154_IEEE802154_2015
#endif
@ -423,28 +426,6 @@ 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 */
@ -546,7 +527,6 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
return 0;
}
#endif /* TSCH_JOIN_SECURED_ONLY */
#if LLSEC802154_ENABLED
if(!tsch_security_parse_frame(input_eb->payload, hdrlen,
input_eb->len - hdrlen - tsch_security_mic_len(&frame),
@ -633,9 +613,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);
@ -952,6 +932,10 @@ tsch_init(void)
* If TSCH_AUTOSTART is not set, one needs to call NETSTACK_MAC.on() to start TSCH. */
NETSTACK_MAC.on();
#endif /* TSCH_AUTOSTART */
#if TSCH_WITH_SIXTOP
sixtop_init();
#endif
}
/*---------------------------------------------------------------------------*/
/* Function send for TSCH-MAC, puts the packet in packetbuf in the MAC queue */
@ -1067,6 +1051,9 @@ packet_input(void)
LOG_INFO("received from ");
LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
LOG_INFO_(" with seqno %u\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
#if TSCH_WITH_SIXTOP
sixtop_input();
#endif /* TSCH_WITH_SIXTOP */
NETSTACK_NETWORK.input();
}
}

View File

@ -301,6 +301,16 @@ nbr_table_register(nbr_table_t *table, nbr_table_callback *callback)
}
}
/*---------------------------------------------------------------------------*/
/* Test whether a specified table has been registered or not */
int
nbr_table_is_register(nbr_table_t *table)
{
if(table != NULL && all_tables[table->index] == table) {
return 1;
}
return 0;
}
/*---------------------------------------------------------------------------*/
/* Returns the first item of the current table */
nbr_table_item_t *
nbr_table_head(nbr_table_t *table)

View File

@ -76,7 +76,7 @@ typedef struct nbr_table {
#define NBR_TABLE_DECLARE(name) extern nbr_table_t *name
typedef enum {
NBR_TABLE_REASON_UNDEFINED,
NBR_TABLE_REASON_UNDEFINED,
NBR_TABLE_REASON_RPL_DIO,
NBR_TABLE_REASON_RPL_DAO,
NBR_TABLE_REASON_RPL_DIS,
@ -86,11 +86,13 @@ typedef enum {
NBR_TABLE_REASON_MAC,
NBR_TABLE_REASON_LLSEC,
NBR_TABLE_REASON_LINK_STATS,
NBR_TABLE_REASON_SIXTOP,
} nbr_table_reason_t;
/** \name Neighbor tables: register and loop through table elements */
/** @{ */
int nbr_table_register(nbr_table_t *table, nbr_table_callback *callback);
int nbr_table_is_register(nbr_table_t *table);
nbr_table_item_t *nbr_table_head(nbr_table_t *table);
nbr_table_item_t *nbr_table_next(nbr_table_t *table, nbr_table_item_t *item);
/** @} */

View File

@ -48,6 +48,9 @@
#undef NETSTACK_CONF_MAC
#define NETSTACK_CONF_MAC tschmac_driver
#undef TSCH_CONF_WITH_SIXTOP
#define TSCH_CONF_WITH_SIXTOP 1
#if CONTIKI_TARGET_COOJA
#define COOJA_CONF_SIMULATE_TURNAROUND 0
#endif /* CONTIKI_TARGET_COOJA */

View File

@ -0,0 +1,163 @@
<?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.contikimote.ContikiMoteType
<identifier>mtype382</identifier>
<description>Cooja Mote Type #1</description>
<source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixtop.c</source>
<commands>make clean TARGET=cooja
make test-sixtop.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>47.60131881808453</x>
<y>20.028921031789082</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>1</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
<eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
</interface_config>
<motetype_identifier>mtype382</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>280</width>
<z>5</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>0.9090909090909091 0.0 0.0 0.9090909090909091 150.72607380174134 154.79188997110083</viewport>
</plugin_config>
<width>400</width>
<z>4</z>
<height>400</height>
<location_x>1</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>1320</width>
<z>3</z>
<height>240</height>
<location_x>400</location_x>
<location_y>160</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<zoomfactor>500.0</zoomfactor>
</plugin_config>
<width>1720</width>
<z>2</z>
<height>166</height>
<location_x>0</location_x>
<location_y>957</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Notes
<plugin_config>
<notes>Enter notes here</notes>
<decorations>true</decorations>
</plugin_config>
<width>1040</width>
<z>1</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>
<analyzers name="6lowpan-pcap" />
</plugin_config>
<width>500</width>
<z>0</z>
<height>300</height>
<location_x>290</location_x>
<location_y>422</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.ScriptRunner
<plugin_config>
<scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile>
<active>true</active>
</plugin_config>
<width>495</width>
<z>0</z>
<height>525</height>
<location_x>663</location_x>
<location_y>105</location_y>
</plugin>
</simconf>

View File

@ -0,0 +1,163 @@
<?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.contikimote.ContikiMoteType
<identifier>mtype382</identifier>
<description>Cooja Mote Type #1</description>
<source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixp-pkt.c</source>
<commands>make clean TARGET=cooja
make test-sixp-pkt.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>47.60131881808453</x>
<y>20.028921031789082</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>1</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
<eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
</interface_config>
<motetype_identifier>mtype382</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>280</width>
<z>5</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>0.9090909090909091 0.0 0.0 0.9090909090909091 150.72607380174134 154.79188997110083</viewport>
</plugin_config>
<width>400</width>
<z>4</z>
<height>400</height>
<location_x>1</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>1320</width>
<z>3</z>
<height>240</height>
<location_x>400</location_x>
<location_y>160</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<zoomfactor>500.0</zoomfactor>
</plugin_config>
<width>1720</width>
<z>2</z>
<height>166</height>
<location_x>0</location_x>
<location_y>957</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Notes
<plugin_config>
<notes>Enter notes here</notes>
<decorations>true</decorations>
</plugin_config>
<width>1040</width>
<z>1</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>
<analyzers name="6lowpan-pcap" />
</plugin_config>
<width>500</width>
<z>0</z>
<height>300</height>
<location_x>290</location_x>
<location_y>422</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.ScriptRunner
<plugin_config>
<scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile>
<active>true</active>
</plugin_config>
<width>495</width>
<z>0</z>
<height>525</height>
<location_x>663</location_x>
<location_y>105</location_y>
</plugin>
</simconf>

View File

@ -0,0 +1,163 @@
<?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.contikimote.ContikiMoteType
<identifier>mtype382</identifier>
<description>Cooja Mote Type #1</description>
<source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixp-trans.c</source>
<commands>make clean TARGET=cooja
make test-sixp-trans.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>47.60131881808453</x>
<y>20.028921031789082</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>1</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
<eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
</interface_config>
<motetype_identifier>mtype382</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>280</width>
<z>5</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>0.9090909090909091 0.0 0.0 0.9090909090909091 150.72607380174134 154.79188997110083</viewport>
</plugin_config>
<width>400</width>
<z>4</z>
<height>400</height>
<location_x>1</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>1320</width>
<z>3</z>
<height>240</height>
<location_x>400</location_x>
<location_y>160</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<zoomfactor>500.0</zoomfactor>
</plugin_config>
<width>1720</width>
<z>2</z>
<height>166</height>
<location_x>0</location_x>
<location_y>957</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Notes
<plugin_config>
<notes>Enter notes here</notes>
<decorations>true</decorations>
</plugin_config>
<width>1040</width>
<z>1</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>
<analyzers name="6lowpan-pcap" />
</plugin_config>
<width>500</width>
<z>0</z>
<height>300</height>
<location_x>290</location_x>
<location_y>422</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.ScriptRunner
<plugin_config>
<scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile>
<active>true</active>
</plugin_config>
<width>495</width>
<z>0</z>
<height>525</height>
<location_x>663</location_x>
<location_y>105</location_y>
</plugin>
</simconf>

View File

@ -0,0 +1,163 @@
<?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.contikimote.ContikiMoteType
<identifier>mtype382</identifier>
<description>Cooja Mote Type #1</description>
<source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixp-nbr.c</source>
<commands>make clean TARGET=cooja
make test-sixp-nbr.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>47.60131881808453</x>
<y>20.028921031789082</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>1</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
<eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
</interface_config>
<motetype_identifier>mtype382</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>280</width>
<z>5</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>0.9090909090909091 0.0 0.0 0.9090909090909091 150.72607380174134 154.79188997110083</viewport>
</plugin_config>
<width>400</width>
<z>4</z>
<height>400</height>
<location_x>1</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>1320</width>
<z>3</z>
<height>240</height>
<location_x>400</location_x>
<location_y>160</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<zoomfactor>500.0</zoomfactor>
</plugin_config>
<width>1720</width>
<z>2</z>
<height>166</height>
<location_x>0</location_x>
<location_y>957</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Notes
<plugin_config>
<notes>Enter notes here</notes>
<decorations>true</decorations>
</plugin_config>
<width>1040</width>
<z>1</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>
<analyzers name="6lowpan-pcap" />
</plugin_config>
<width>500</width>
<z>0</z>
<height>300</height>
<location_x>290</location_x>
<location_y>422</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.ScriptRunner
<plugin_config>
<scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile>
<active>true</active>
</plugin_config>
<width>495</width>
<z>0</z>
<height>525</height>
<location_x>663</location_x>
<location_y>105</location_y>
</plugin>
</simconf>

View File

@ -0,0 +1,163 @@
<?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.contikimote.ContikiMoteType
<identifier>mtype382</identifier>
<description>Cooja Mote Type #1</description>
<source>[CONTIKI_DIR]/tests/16-6tisch/code/test-sixp.c</source>
<commands>make clean TARGET=cooja
make test-sixp.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>47.60131881808453</x>
<y>20.028921031789082</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>1</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
<eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
</interface_config>
<motetype_identifier>mtype382</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>280</width>
<z>5</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>0.9090909090909091 0.0 0.0 0.9090909090909091 150.72607380174134 154.79188997110083</viewport>
</plugin_config>
<width>400</width>
<z>4</z>
<height>400</height>
<location_x>1</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>1320</width>
<z>3</z>
<height>240</height>
<location_x>400</location_x>
<location_y>160</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.TimeLine
<plugin_config>
<mote>0</mote>
<showRadioRXTX />
<showRadioHW />
<showLEDs />
<zoomfactor>500.0</zoomfactor>
</plugin_config>
<width>1720</width>
<z>2</z>
<height>166</height>
<location_x>0</location_x>
<location_y>957</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Notes
<plugin_config>
<notes>Enter notes here</notes>
<decorations>true</decorations>
</plugin_config>
<width>1040</width>
<z>1</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>
<analyzers name="6lowpan-pcap" />
</plugin_config>
<width>500</width>
<z>0</z>
<height>300</height>
<location_x>290</location_x>
<location_y>422</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.ScriptRunner
<plugin_config>
<scriptfile>[CONTIKI_DIR]/tests/16-6tisch/js/unit-test.js</scriptfile>
<active>true</active>
</plugin_config>
<width>495</width>
<z>0</z>
<height>525</height>
<location_x>663</location_x>
<location_y>105</location_y>
</plugin>
</simconf>

1
tests/16-6tisch/Makefile Normal file
View File

@ -0,0 +1 @@
include ../Makefile.simulation-test

View File

@ -0,0 +1,15 @@
all:
CFLAGS += -D PROJECT_CONF_H=\"project-conf.h\"
APPS += unit-test
MODULES += os/net/mac/tsch os/net/mac/tsch/sixtop
PROJECT_SOURCEFILES += common.c
ifeq ($(TEST_04),1)
CFLAGS += -DSIXP_MSG_API_TEST=1
endif
CONTIKI = ../../..
CONTIKI_WITH_IPV6 = 1
include $(CONTIKI)/Makefile.include

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2017, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
#include <stdio.h>
#include "net/mac/tsch/sixtop/sixtop.h"
#include "unit-test/unit-test.h"
#include "common.h"
#include "lib/simEnvChange.h"
#include "sys/cooja_mt.h"
static uint8_t send_is_called;
void
test_print_report(const unit_test_t *utp)
{
printf("=check-me= ");
if(utp->result == unit_test_failure) {
printf("FAILED - %s: exit at L%u\n", utp->descr, utp->exit_line);
} else {
printf("SUCCEEDED - %s\n", utp->descr);
}
/* give up the CPU so that the mote can output messages in the serial buffer */
simProcessRunValue = 1;
cooja_mt_yield();
}
uint8_t
test_mac_send_function_is_called(void)
{
return send_is_called;
}
static void
init(void)
{
send_is_called = 0;
}
static void
send(mac_callback_t sent_callback, void *ptr)
{
send_is_called = 1;
}
const struct mac_driver test_mac_driver = {
"Test MAC",
init,
send,
NULL,
NULL,
NULL
};

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2017, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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 _COMMON_H
#define _COMMON_H
#include "unit-test/unit-test.h"
void test_print_report(const unit_test_t *utp);
uint8_t test_mac_send_function_is_called(void);
extern const struct mac_driver test_mac_driver;
#endif /* !_COMMON_H */

View File

@ -0,0 +1,78 @@
/*
* Copyright (c) 2017, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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_
#if CONTIKI_TARGET_COOJA
#define COOJA_CONF_SIMULATE_TURNAROUND 0
#else
//#error "This file is intended to be used for Cooja mote."
#endif /* CONTIKI_TARGET_COOJA */
#undef SIXTOP_CONF_MAX_SCHEDULING_FUNCTIONS
#define SIXTOP_CONF_MAX_SCHEDULING_FUNCTIONS 2
#undef SIXTOP_CONF_MAX_TRANSACTIONS
#define SIXTOP_CONF_MAX_TRANSACTIONS 2
#undef SIXP_CONF_WITH_PAYLOAD_TERMINATION_IE
#define SIXP_CONF_WITH_PAYLOAD_TERMINATION_IE 1
#undef NBR_TABLE_CONF_MAX_NEIGHBORS
#define NBR_TABLE_CONF_MAX_NEIGHBORS 2
#define UNIT_TEST_PRINT_FUNCTION test_print_report
#undef TSCH_CONF_WITH_SIXTOP
#define TSCH_CONF_WITH_SIXTOP 1
#undef TSCH_LOG_CONF_PER_SLOT
#define TSCH_LOG_CONF_PER_SLOT 1
#undef TSCH_CONF_AUTOSTART
#define TSCH_CONF_AUTOSTART 0
#undef IEEE802154_CONF_PANID
#define IEEE802154_CONF_PANID 0xabcd
#undef NETSTACK_CONF_MAC
#define NETSTACK_CONF_MAC test_mac_driver
#undef NETSTACK_CONF_RDC
#define NETSTACK_CONF_RDC nordc_driver
#undef NETSTACK_CONF_FRAMER
#define NETSTACK_CONF_FRAMER framer_802154
#undef FRAME802154_CONF_VERSION
#define FRAME802154_CONF_VERSION FRAME802154_IEEE802154_2015
#endif /* __PROJECT_CONF_H__ */

View File

@ -0,0 +1,224 @@
/*
* Copyright (c) 2017, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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 STEP OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "contiki.h"
#include "contiki-net.h"
#include "contiki-lib.h"
#include "lib/assert.h"
#include "net/mac/tsch/sixtop/sixp-nbr.h"
#include "unit-test/unit-test.h"
#include "common.h"
static linkaddr_t peer_addr_1;
static linkaddr_t peer_addr_2;
static linkaddr_t peer_addr_3;
PROCESS(test_process, "6P neighbor APIs test");
AUTOSTART_PROCESSES(&test_process);
static void
test_setup(void)
{
sixp_nbr_init();
memset(&peer_addr_1, 0, sizeof(peer_addr_1));
peer_addr_1.u8[0] = 1;
memset(&peer_addr_2, 0, sizeof(peer_addr_2));
peer_addr_2.u8[0] = 2;
memset(&peer_addr_3, 0, sizeof(peer_addr_3));
peer_addr_3.u8[0] = 3;
}
UNIT_TEST_REGISTER(test_alloc_and_free,
"test sixp_nbr_{alloc,free}");
UNIT_TEST(test_alloc_and_free)
{
sixp_nbr_t *nbr;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_1) == NULL);
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_2) == NULL);
/* a valid allocation */
UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr_1)) != NULL);
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_1) == nbr);
/* another allocation */
UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr_2)) != NULL);
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_2) == nbr);
/* no available memory because NBR_TABLE_CONF_MAX_NEIGHBORS == 2 */
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_3) == NULL);
UNIT_TEST_ASSERT(sixp_nbr_alloc(&peer_addr_3) == NULL);
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_3) == NULL);
/* cannot allocate a duplicate nbr */
UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr_1)) == NULL);
UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr_2)) == NULL);
/* remove allocated nbrs */
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_1) != NULL);
sixp_nbr_free(sixp_nbr_find(&peer_addr_1));
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_1) == NULL);
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_2) != NULL);
sixp_nbr_free(sixp_nbr_find(&peer_addr_2));
UNIT_TEST_ASSERT(sixp_nbr_find(&peer_addr_2) == NULL);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_gtx_management,
"test GTX Management");
UNIT_TEST(test_gtx_management)
{
sixp_nbr_t *nbr;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr_1)) != NULL);
UNIT_TEST_ASSERT(sixp_nbr_get_gtx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_advance_gtx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_gtx(nbr) == 0x01);
UNIT_TEST_ASSERT(sixp_nbr_advance_gtx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_gtx(nbr) == 0x02);
UNIT_TEST_ASSERT(sixp_nbr_advance_gtx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_gtx(nbr) == 0x01);
UNIT_TEST_ASSERT(sixp_nbr_advance_gtx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_gtx(nbr) == 0x02);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_grx_management,
"test GRX Management");
UNIT_TEST(test_grx_management)
{
sixp_nbr_t *nbr;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr_1)) != NULL);
UNIT_TEST_ASSERT(sixp_nbr_get_grx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_advance_grx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_grx(nbr) == 0x01);
UNIT_TEST_ASSERT(sixp_nbr_advance_grx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_grx(nbr) == 0x02);
UNIT_TEST_ASSERT(sixp_nbr_advance_grx(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_grx(nbr) == 0x01);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_next_seqno,
"test next_seqno operation");
UNIT_TEST(test_next_seqno)
{
sixp_nbr_t *nbr;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr_1)) != NULL);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 1);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 2);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 3);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 4);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 5);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 6);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 7);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 8);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 9);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 10);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 11);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 12);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 13);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 14);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 15);
UNIT_TEST_ASSERT(sixp_nbr_increment_next_seqno(nbr) == 0);
UNIT_TEST_ASSERT(sixp_nbr_get_next_seqno(nbr) == 0);
UNIT_TEST_END();
}
PROCESS_THREAD(test_process, ev, data)
{
PROCESS_BEGIN();
printf("Run unit-test\n");
printf("---\n");
/* alloc / free */
UNIT_TEST_RUN(test_alloc_and_free);
/* GTX */
UNIT_TEST_RUN(test_gtx_management);
/* GRX */
UNIT_TEST_RUN(test_grx_management);
/* next sequence number */
UNIT_TEST_RUN(test_next_seqno);
printf("=check-me= DONE\n");
PROCESS_END();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,592 @@
/*
* Copyright (c) 2017, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
#include <stdio.h>
#include "contiki.h"
#include "contiki-net.h"
#include "contiki-lib.h"
#include "lib/assert.h"
#include "net/packetbuf.h"
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/sixtop/sixtop.h"
#include "net/mac/tsch/sixtop/sixp.h"
#include "net/mac/tsch/sixtop/sixp-nbr.h"
#include "net/mac/tsch/sixtop/sixp-trans.h"
#include "unit-test/unit-test.h"
#include "common.h"
#define UNKNOWN_SF_SFID 0
#define TEST_SF_SFID 0xf1
static linkaddr_t peer_addr;
static uint8_t test_sf_input_is_called = 0;
static void
input(sixp_pkt_type_t type,sixp_pkt_code_t code, const uint8_t *body,
uint16_t body_len, const linkaddr_t *peer_addr)
{
test_sf_input_is_called = 1;
}
static const sixtop_sf_t test_sf = {
TEST_SF_SFID,
0,
NULL,
input,
NULL
};
PROCESS(test_process, "6top protocol APIs test");
AUTOSTART_PROCESSES(&test_process);
static void
test_setup(void)
{
test_mac_driver.init();
sixtop_init();
packetbuf_clear();
memset(&peer_addr, 0, sizeof(peer_addr));
sixtop_add_sf(&test_sf);
test_sf_input_is_called = 0;
}
UNIT_TEST_REGISTER(test_input_no_sf,
"sixp_input(no_sf)");
UNIT_TEST(test_input_no_sf)
{
uint32_t body;
uint8_t *p;
UNIT_TEST_BEGIN();
test_setup();
memset(&body, 0, sizeof(body));
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
UNKNOWN_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
NULL) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr);
p = packetbuf_hdrptr();
/* length */
UNIT_TEST_ASSERT(packetbuf_totlen() == 11);
/* Termination 1 IE */
UNIT_TEST_ASSERT(p[0] == 0x00);
UNIT_TEST_ASSERT(p[1] == 0x3f);
/* IETF IE */
UNIT_TEST_ASSERT(p[2] == 0x05);
UNIT_TEST_ASSERT(p[3] == 0xa8);
/* 6top IE */
UNIT_TEST_ASSERT(p[4] == 0x00);
UNIT_TEST_ASSERT(p[5] == 0x11);
UNIT_TEST_ASSERT(p[6] == 0x08);
UNIT_TEST_ASSERT(p[7] == UNKNOWN_SF_SFID);
UNIT_TEST_ASSERT(p[8] == 0x0a);
/* Payload Termination IE */
UNIT_TEST_ASSERT(p[9] == 0x00);
UNIT_TEST_ASSERT(p[10] == 0xf8);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 1);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_input_busy,
"sixp_input(busy)");
UNIT_TEST(test_input_busy)
{
uint8_t *p;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
/* send a request to the peer first */
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_trans_find(&peer_addr) == NULL);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_CLEAR,
TEST_SF_SFID, NULL, 0, &peer_addr,
NULL, NULL, 0) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 1);
UNIT_TEST_ASSERT(sixp_trans_find(&peer_addr) != NULL);
test_mac_driver.init(); /* clear test_mac_send_is_called status */
memset(&body, 0, sizeof(body));
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
NULL) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr);
p = packetbuf_hdrptr();
/* length */
UNIT_TEST_ASSERT(packetbuf_totlen() == 11);
/* Termination 1 IE */
UNIT_TEST_ASSERT(p[0] == 0x00);
UNIT_TEST_ASSERT(p[1] == 0x3f);
/* IETF IE */
UNIT_TEST_ASSERT(p[2] == 0x05);
UNIT_TEST_ASSERT(p[3] == 0xa8);
/* 6top IE */
UNIT_TEST_ASSERT(p[4] == 0x00);
UNIT_TEST_ASSERT(p[5] == 0x11);
UNIT_TEST_ASSERT(p[6] == 0x0a);
UNIT_TEST_ASSERT(p[7] == TEST_SF_SFID);
UNIT_TEST_ASSERT(p[8] == 0x0a);
/* Payload Termination IE */
UNIT_TEST_ASSERT(p[9] == 0x00);
UNIT_TEST_ASSERT(p[10] == 0xf8);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 1);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_input_no_memory,
"sixp_input(no_memory)");
UNIT_TEST(test_input_no_memory)
{
uint32_t body;
sixp_pkt_t pkt;
uint8_t *p;
linkaddr_t addr;
UNIT_TEST_BEGIN();
test_setup();
memset(&body, 0, sizeof(body));
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
&pkt) == 0);
memset(&addr, 0, sizeof(addr));
addr.u8[0] = 1;
UNIT_TEST_ASSERT(sixp_trans_alloc(&pkt, &addr) != NULL);
addr.u8[0] = 2;
UNIT_TEST_ASSERT(sixp_trans_alloc(&pkt, &addr) != NULL);
addr.u8[0] = 3;
/* no memory left for another transaction */
UNIT_TEST_ASSERT(sixp_trans_alloc(&pkt, &addr) == NULL);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr);
p = packetbuf_hdrptr();
/* length */
UNIT_TEST_ASSERT(packetbuf_totlen() == 11);
/* Termination 1 IE */
UNIT_TEST_ASSERT(p[0] == 0x00);
UNIT_TEST_ASSERT(p[1] == 0x3f);
/* IETF IE */
UNIT_TEST_ASSERT(p[2] == 0x05);
UNIT_TEST_ASSERT(p[3] == 0xa8);
/* 6top IE */
UNIT_TEST_ASSERT(p[4] == 0x00);
UNIT_TEST_ASSERT(p[5] == 0x11);
UNIT_TEST_ASSERT(p[6] == 0x0b);
UNIT_TEST_ASSERT(p[7] == TEST_SF_SFID);
UNIT_TEST_ASSERT(p[8] == 0x0a);
/* Payload Termination IE */
UNIT_TEST_ASSERT(p[9] == 0x00);
UNIT_TEST_ASSERT(p[10] == 0xf8);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 1);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_input_schedule_generation,
"sixp_input(schedule_generation)");
UNIT_TEST(test_input_schedule_generation)
{
sixp_nbr_t *nbr;
sixp_trans_t *trans;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
memset(&body, 0, sizeof(body));
UNIT_TEST_ASSERT((nbr = sixp_nbr_alloc(&peer_addr)) != NULL);
/* nbr has GTX 0 and GRX 0 now */
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 1, 1,
(const uint8_t *)&body, sizeof(body),
NULL) == 0);
sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr);
UNIT_TEST_ASSERT(test_sf_input_is_called == 0);
UNIT_TEST_ASSERT(sixp_nbr_advance_gtx(nbr) == 0);
sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr);
UNIT_TEST_ASSERT(test_sf_input_is_called == 0);
UNIT_TEST_ASSERT(sixp_nbr_advance_grx(nbr) == 0);
sixp_input(packetbuf_hdrptr(), packetbuf_totlen(), &peer_addr);
UNIT_TEST_ASSERT(test_sf_input_is_called == 1);
UNIT_TEST_ASSERT((trans = sixp_trans_find(&peer_addr)) != NULL);
UNIT_TEST_ASSERT(sixp_trans_get_state(trans) ==
SIXP_TRANS_STATE_REQUEST_RECEIVED);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_request_1,
"sixp_output(request_1)");
UNIT_TEST(test_output_request_1)
{
sixp_pkt_t pkt;
sixp_trans_t *trans;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
memset(&body, 0, sizeof(body));
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
&pkt) == 0);
UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL);
memset(&body, 0, sizeof(body));
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, (uint8_t *)&body, sizeof(body),
&peer_addr, NULL, NULL, 0) == -1);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_request_2,
"sixp_output(request_2)");
UNIT_TEST(test_output_request_2)
{
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
memset(&body, 0, sizeof(body));
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, (uint8_t *)&body, sizeof(body),
&peer_addr, NULL, NULL, 0) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 1);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_response_1,
"sixp_output(response_1)");
UNIT_TEST(test_output_response_1)
{
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
TEST_SF_SFID, NULL, 0,
&peer_addr, NULL, NULL, 0) == -1);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_response_2,
"sixp_output(response_2)");
UNIT_TEST(test_output_response_2)
{
sixp_pkt_t pkt;
sixp_trans_t *trans;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
&pkt) == 0);
UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
TEST_SF_SFID, NULL, 0,
&peer_addr, NULL, NULL, 0) == -1);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_response_3,
"sixp_output(response_3)");
UNIT_TEST(test_output_response_3)
{
sixp_pkt_t pkt;
sixp_trans_t *trans;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
&pkt) == 0);
UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL);
UNIT_TEST_ASSERT(
sixp_trans_transit_state(trans, SIXP_TRANS_STATE_REQUEST_RECEIVED) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
TEST_SF_SFID, NULL, 0,
&peer_addr, NULL, NULL, 0) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 1);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_response_4,
"sixp_output(response_4)");
UNIT_TEST(test_output_response_4)
{
sixp_pkt_t pkt;
sixp_trans_t *trans;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
&pkt) == 0);
UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL);
UNIT_TEST_ASSERT(
sixp_trans_transit_state(trans, SIXP_TRANS_STATE_REQUEST_SENT) == 0);
UNIT_TEST_ASSERT(
sixp_trans_transit_state(trans, SIXP_TRANS_STATE_RESPONSE_RECEIVED) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_RESPONSE,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
TEST_SF_SFID, NULL, 0,
&peer_addr, NULL, NULL, 0) == -1);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_confirmation_1,
"sixp_output(confirmation_1)");
UNIT_TEST(test_output_confirmation_1)
{
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_CONFIRMATION,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
TEST_SF_SFID, NULL, 0,
&peer_addr, NULL, NULL, 0) == -1);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_confirmation_2,
"sixp_output(confirmation_2)");
UNIT_TEST(test_output_confirmation_2)
{
sixp_pkt_t pkt;
sixp_trans_t *trans;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
&pkt) == 0);
UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_CONFIRMATION,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
TEST_SF_SFID, NULL, 0,
&peer_addr, NULL, NULL, 0) == -1);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_confirmation_3,
"sixp_output(confirmation_3)");
UNIT_TEST(test_output_confirmation_3)
{
sixp_pkt_t pkt;
sixp_trans_t *trans;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
&pkt) == 0);
UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL);
UNIT_TEST_ASSERT(
sixp_trans_transit_state(trans, SIXP_TRANS_STATE_REQUEST_SENT) == 0);
UNIT_TEST_ASSERT(
sixp_trans_transit_state(trans, SIXP_TRANS_STATE_RESPONSE_RECEIVED) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_CONFIRMATION,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
TEST_SF_SFID, NULL, 0,
&peer_addr, NULL, NULL, 0) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 1);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output_confirmation_4,
"sixp_output(confirmation_4)");
UNIT_TEST(test_output_confirmation_4)
{
sixp_pkt_t pkt;
sixp_trans_t *trans;
uint32_t body;
UNIT_TEST_BEGIN();
test_setup();
UNIT_TEST_ASSERT(sixp_pkt_create(SIXP_PKT_TYPE_REQUEST,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_CMD_ADD,
TEST_SF_SFID, 10, 0, 0,
(const uint8_t *)&body, sizeof(body),
&pkt) == 0);
UNIT_TEST_ASSERT((trans = sixp_trans_alloc(&pkt, &peer_addr)) != NULL);
UNIT_TEST_ASSERT(
sixp_trans_transit_state(trans, SIXP_TRANS_STATE_REQUEST_SENT) == 0);
UNIT_TEST_ASSERT(
sixp_trans_transit_state(trans, SIXP_TRANS_STATE_RESPONSE_RECEIVED) == 0);
UNIT_TEST_ASSERT(
sixp_trans_transit_state(trans,
SIXP_TRANS_STATE_CONFIRMATION_SENT) == 0);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_ASSERT(sixp_output(SIXP_PKT_TYPE_CONFIRMATION,
(sixp_pkt_code_t)(uint8_t)SIXP_PKT_RC_SUCCESS,
TEST_SF_SFID, NULL, 0,
&peer_addr, NULL, NULL, 0) == -1);
UNIT_TEST_ASSERT(test_mac_send_function_is_called() == 0);
UNIT_TEST_END();
}
PROCESS_THREAD(test_process, ev, data)
{
static struct etimer et;
PROCESS_BEGIN();
/* wait until the sixtop module gets ready */
etimer_set(&et, CLOCK_SECOND);
tschmac_driver.init();
tschmac_driver.on();
tsch_set_coordinator(1);
while(tsch_is_associated == 0) {
PROCESS_YIELD_UNTIL(etimer_expired(&et));
etimer_reset(&et);
}
printf("Run unit-test\n");
printf("---\n");
UNIT_TEST_RUN(test_input_no_sf);
UNIT_TEST_RUN(test_input_busy);
UNIT_TEST_RUN(test_input_no_memory);
UNIT_TEST_RUN(test_input_schedule_generation);
UNIT_TEST_RUN(test_output_request_1);
UNIT_TEST_RUN(test_output_request_2);
UNIT_TEST_RUN(test_output_response_1);
UNIT_TEST_RUN(test_output_response_2);
UNIT_TEST_RUN(test_output_response_3);
UNIT_TEST_RUN(test_output_response_4);
UNIT_TEST_RUN(test_output_confirmation_1);
UNIT_TEST_RUN(test_output_confirmation_2);
UNIT_TEST_RUN(test_output_confirmation_3);
UNIT_TEST_RUN(test_output_confirmation_4);
printf("=check-me= DONE\n");
PROCESS_END();
}

View File

@ -0,0 +1,260 @@
/*
* Copyright (c) 2017, Yasuyuki Tanaka
* 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 copyright holder 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 COPYRIGHT HOLDERS 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
* COPYRIGHT HOLDER 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.
*/
#include <stdio.h>
#include "contiki.h"
#include "contiki-net.h"
#include "contiki-lib.h"
#include "lib/assert.h"
#include "net/packetbuf.h"
#include "net/mac/tsch/sixtop/sixtop.h"
#include "net/mac/tsch/sixtop/sixtop-conf.h"
#include "unit-test/unit-test.h"
#include "common.h"
#if SIXTOP_MAX_SCHEDULING_FUNCTIONS != 2
#error SIXTOP_CONF_MAX_SCHEDULING_FUNCTIONS must be set with 2 for this test
#endif
#define TEST_SF1_SFID 0xf1
#define TEST_SF2_SFID 0xf2
#define TEST_SF3_SFID 0xf3
static uint8_t sf_init_vector;
static void test_sf1_init(void);
static void test_sf2_init(void);
static void test_sf3_init(void);
static void reset_sf_init_vector(void);
static const sixtop_sf_t test_sf1 = {
TEST_SF1_SFID,
0,
test_sf1_init,
NULL,
NULL
};
static const sixtop_sf_t test_sf2 = {
TEST_SF2_SFID,
0,
test_sf2_init,
NULL,
NULL
};
static const sixtop_sf_t test_sf3 = {
TEST_SF3_SFID,
0,
test_sf3_init,
NULL,
NULL
};
static void
test_sf1_init(void)
{
sf_init_vector |= TEST_SF1_SFID;
}
static void
test_sf2_init(void)
{
sf_init_vector |= TEST_SF2_SFID;
}
static void
test_sf3_init(void)
{
sf_init_vector |= TEST_SF3_SFID;
}
void
reset_sf_init_vector(void)
{
sf_init_vector = 0;
}
PROCESS(test_process, "6top module APIs test");
AUTOSTART_PROCESSES(&test_process);
UNIT_TEST_REGISTER(test_add_sf,
"sixtop_add_sf() should add a SF");
UNIT_TEST(test_add_sf)
{
UNIT_TEST_BEGIN();
/* confirm any of test_sf{1,2,3} is not added yet. */
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF1_SFID) == NULL);
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF2_SFID) == NULL);
/* add test_sf1 */
UNIT_TEST_ASSERT(sixtop_add_sf(&test_sf1) == 0);
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF1_SFID) == &test_sf1);
/* add test_sf2 */
UNIT_TEST_ASSERT(sixtop_add_sf(&test_sf2) == 0);
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF2_SFID) == &test_sf2);
/*
* add test_sf3; should fail because of lack of memory.
* SIXTOP_MAX_SCHEDULING_FUNCTIONS is set with two.
*/
UNIT_TEST_ASSERT(sixtop_add_sf(&test_sf3) == -1);
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF3_SFID) == NULL);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_find_sf,
"sixtop_find_sf() should find a SF which has been added");
UNIT_TEST(test_find_sf)
{
UNIT_TEST_BEGIN();
/*
* See test_add_sf(); sixtop_find_sf() is tested together with sixtop_add_sf()
* in it.
*/
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_init,
"sixtop_init() should remove all SFs in the 6top module");
UNIT_TEST(test_init)
{
UNIT_TEST_BEGIN();
/* set up a precondition where some SFs has been added */
if(sixtop_find_sf(TEST_SF1_SFID) == NULL) {
UNIT_TEST_ASSERT(sixtop_add_sf(&test_sf1) == 0);
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF1_SFID) != NULL);
}
if(sixtop_find_sf(TEST_SF2_SFID) == NULL) {
UNIT_TEST_ASSERT(sixtop_add_sf(&test_sf2) == 0);
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF2_SFID) != NULL);
}
/* call sixtop_init() which removes all the SFs in the module */
sixtop_init();
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF1_SFID) == NULL);
UNIT_TEST_ASSERT(sixtop_find_sf(TEST_SF2_SFID) == NULL);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_output,
"test sixtop_output()");
UNIT_TEST(test_output)
{
linkaddr_t peer_addr;
uint8_t *p;
UNIT_TEST_BEGIN();
packetbuf_clear();
UNIT_TEST_ASSERT(packetbuf_hdralloc(1) > 0);
p = packetbuf_hdrptr();
p[0] = 0xca; // header
p = packetbuf_dataptr();
p[0] = 0xfe; // data
packetbuf_set_datalen(1);
sixtop_output(&peer_addr, NULL, NULL);
p = packetbuf_hdrptr();
/* Length */
UNIT_TEST_ASSERT(packetbuf_totlen() == 9);
/* Termination 1 IE */
UNIT_TEST_ASSERT(p[0] == 0x00);
UNIT_TEST_ASSERT(p[1] == 0x3f);
/* IETF IE */
UNIT_TEST_ASSERT(p[2] == 0x03);
UNIT_TEST_ASSERT(p[3] == 0xa8);
/* 6top IE Sub-ID */
UNIT_TEST_ASSERT(p[4] == 0x00);
/* test data set above */
UNIT_TEST_ASSERT(p[5] == 0xca);
UNIT_TEST_ASSERT(p[6] == 0xfe);
/* Payload Termination IE */
UNIT_TEST_ASSERT(p[7] == 0x00);
UNIT_TEST_ASSERT(p[8] == 0xf8);
UNIT_TEST_END();
}
UNIT_TEST_REGISTER(test_init_sf,
"sixtop_init_sf() should invoke every SF->init()");
UNIT_TEST(test_init_sf)
{
UNIT_TEST_BEGIN();
/* remove all the SFs in the 6top module */
sixtop_init();
/* add test_sf1 */
UNIT_TEST_ASSERT(sixtop_add_sf(&test_sf1) == 0);
reset_sf_init_vector();
sixtop_init_sf();
UNIT_TEST_ASSERT(sf_init_vector == TEST_SF1_SFID);
/* add test_sf2 */
UNIT_TEST_ASSERT(sixtop_add_sf(&test_sf2) == 0);
reset_sf_init_vector();
sixtop_init_sf();
UNIT_TEST_ASSERT(sf_init_vector == (TEST_SF1_SFID | TEST_SF2_SFID));
UNIT_TEST_END();
}
PROCESS_THREAD(test_process, ev, data)
{
PROCESS_BEGIN();
printf("Run unit-test\n");
printf("---\n");
UNIT_TEST_RUN(test_add_sf);
UNIT_TEST_RUN(test_find_sf);
UNIT_TEST_RUN(test_init);
UNIT_TEST_RUN(test_init_sf);
UNIT_TEST_RUN(test_output);
printf("=check-me= DONE\n");
PROCESS_END();
}

View File

@ -0,0 +1,27 @@
TIMEOUT(10000, log.testFailed());
var failed = false;
var done = 0;
while(done < sim.getMotes().length) {
YIELD();
log.log(time + " " + "node-" + id + " "+ msg + "\n");
if(msg.contains("=check-me=") == false) {
continue;
}
if(msg.contains("FAILED")) {
failed = true;
}
if(msg.contains("DONE")) {
done++;
}
}
if(failed) {
log.testFailed();
}
log.testOK();