Merge pull request #55 from simonduq/pr/shell

A new Shell!
This commit is contained in:
Nicolas Tsiftes 2017-08-25 14:52:55 +02:00 committed by GitHub
commit fd5ebc8d42
64 changed files with 1581 additions and 352 deletions

81
apps/shell/serial-shell.c Normal file
View File

@ -0,0 +1,81 @@
/*
* Copyright (c) 2008, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* A shell back-end for the serial port
* \author
* Adam Dunkels <adam@sics.se>
* Simon Duquennoy <simon.duquennoy@inria.fr>
*/
/**
* \addtogroup shell
* @{
*/
#include "contiki.h"
#include "dev/serial-line.h"
#include "sys/log.h"
#include "shell.h"
#include "serial-shell.h"
/*---------------------------------------------------------------------------*/
PROCESS(serial_shell_process, "Contiki serial shell");
/*---------------------------------------------------------------------------*/
static void
serial_shell_output(const char *str) {
printf("%s", str);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(serial_shell_process, ev, data)
{
PROCESS_BEGIN();
shell_init();
while(1) {
static struct pt shell_input_pt;
PROCESS_WAIT_EVENT_UNTIL(ev == serial_line_event_message && data != NULL);
PROCESS_PT_SPAWN(&shell_input_pt, shell_input(&shell_input_pt, serial_shell_output, data));
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
void
serial_shell_init(void)
{
process_start(&serial_shell_process, NULL);
}
/*---------------------------------------------------------------------------*/
/** @} */

49
apps/shell/serial-shell.h Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2008, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* A shell back-end for the serial port
* \author
* Adam Dunkels <adam@sics.se>
* Simon Duquennoy <simon.duquennoy@inria.fr>
*/
#ifndef SERIAL_SHELL_H_
#define SERIAL_SHELL_H_
/**
* Initializes Serial Shell module
*/
void serial_shell_init(void);
#endif /* SERIAL_SHELL_H_ */

626
apps/shell/shell-commands.c Normal file
View File

@ -0,0 +1,626 @@
/*
* Copyright (c) 2017, Inria.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* The Contiki shell commands
* \author
* Simon Duquennoy <simon.duquennoy@inria.fr>
*/
/**
* \addtogroup shell
* @{
*/
#include "contiki.h"
#include "shell.h"
#include "shell-commands.h"
#include "sys/log.h"
#include "net/ip/uip.h"
#include "net/ip/uiplib.h"
#include "net/ipv6/uip-icmp6.h"
#include "net/ipv6/uip-ds6.h"
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/tsch-adaptive-timesync.h"
#include "net/mac/tsch/tsch-queue.h"
#include "net/mac/tsch/tsch-log.h"
#include "net/mac/tsch/tsch-private.h"
#if UIP_CONF_IPV6_RPL_LITE == 1
#include "net/rpl-lite/rpl.h"
#else /* UIP_CONF_IPV6_RPL_LITE == 1 */
#include "net/rpl/rpl.h"
#include "net/rpl/rpl-private.h"
#endif /* UIP_CONF_IPV6_RPL_LITE == 1 */
#include <stdlib.h>
#define PING_TIMEOUT (5 * CLOCK_SECOND)
static struct uip_icmp6_echo_reply_notification echo_reply_notification;
static shell_output_func *curr_ping_output_func = NULL;
static struct process *curr_ping_process;
static uint8_t curr_ping_ttl;
static uint16_t curr_ping_datalen;
/*---------------------------------------------------------------------------*/
static const char *
ds6_nbr_state_to_str(uint8_t state)
{
switch(state) {
case NBR_INCOMPLETE:
return "Incomplete";
case NBR_REACHABLE:
return "Reachable";
case NBR_STALE:
return "Stale";
case NBR_DELAY:
return "Delay";
case NBR_PROBE:
return "Probe";
default:
return "Unknown";
}
}
/*---------------------------------------------------------------------------*/
static const char *
rpl_state_to_str(enum rpl_dag_state state)
{
switch(state) {
case DAG_INITIALIZED:
return "Initialized";
case DAG_JOINED:
return "Joined";
case DAG_REACHABLE:
return "Reachable";
case DAG_POISONING:
return "Poisoning";
default:
return "Unknown";
}
}
/*---------------------------------------------------------------------------*/
static const char *
rpl_mop_to_str(int mop)
{
switch(mop) {
case RPL_MOP_NO_DOWNWARD_ROUTES:
return "No downward routes";
case RPL_MOP_NON_STORING:
return "Non-storing";
case RPL_MOP_STORING_NO_MULTICAST:
return "Storing";
case RPL_MOP_STORING_MULTICAST:
return "Storing+multicast";
default:
return "Unknown";
}
}
/*---------------------------------------------------------------------------*/
static const char *
rpl_ocp_to_str(int ocp)
{
switch(ocp) {
case RPL_OCP_OF0:
return "OF0";
case RPL_OCP_MRHOF:
return "MRHOF";
default:
return "Unknown";
}
}
/*---------------------------------------------------------------------------*/
static void
echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen)
{
if(curr_ping_output_func != NULL) {
curr_ping_output_func = NULL;
curr_ping_ttl = ttl;
curr_ping_datalen = datalen;
process_poll(curr_ping_process);
}
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, char *args))
{
static uip_ipaddr_t remote_addr;
static struct etimer timeout_timer;
char *next_args;
PT_BEGIN(pt);
SHELL_ARGS_INIT(args, next_args);
/* Get argument (remote IPv6) */
SHELL_ARGS_NEXT(args, next_args);
if(uiplib_ipaddrconv(args, &remote_addr) == 0) {
SHELL_OUTPUT(output, "Invalid IPv6: %s\n", args);
PT_EXIT(pt);
}
SHELL_OUTPUT(output, "Pinging ");
shell_output_6addr(output, &remote_addr);
SHELL_OUTPUT(output, "\n");
/* Send ping request */
curr_ping_process = PROCESS_CURRENT();
curr_ping_output_func = output;
etimer_set(&timeout_timer, PING_TIMEOUT);
uip_icmp6_send(&remote_addr, ICMP6_ECHO_REQUEST, 0, 4);
PT_WAIT_UNTIL(pt, curr_ping_output_func == NULL || etimer_expired(&timeout_timer));
if(curr_ping_output_func != NULL) {
SHELL_OUTPUT(output, "Timeout\n");
curr_ping_output_func = NULL;
} else {
SHELL_OUTPUT(output, "Received ping reply from ");
shell_output_6addr(output, &remote_addr);
SHELL_OUTPUT(output, ", len %u, ttl %u, delay %lu ms\n",
curr_ping_datalen, curr_ping_ttl, (1000*(clock_time() - timeout_timer.timer.start))/CLOCK_SECOND);
}
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args))
{
static int is_on;
static uip_ipaddr_t prefix;
char *next_args;
PT_BEGIN(pt);
SHELL_ARGS_INIT(args, next_args);
/* Get first arg (0/1) */
SHELL_ARGS_NEXT(args, next_args);
if(!strcmp(args, "1")) {
is_on = 1;
} else if(!strcmp(args, "0")) {
is_on = 0;
} else {
SHELL_OUTPUT(output, "Invalid argument: %s\n", args);
PT_EXIT(pt);
}
/* Get first second arg (prefix) */
SHELL_ARGS_NEXT(args, next_args);
if(args != NULL) {
if(uiplib_ipaddrconv(args, &prefix) == 0) {
SHELL_OUTPUT(output, "Invalid Prefix: %s\n", args);
PT_EXIT(pt);
}
} else {
uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
}
if(is_on) {
if(!rpl_dag_root_is_root()) {
SHELL_OUTPUT(output, "Setting as DAG root with prefix ");
shell_output_6addr(output, &prefix);
SHELL_OUTPUT(output, "\n");
rpl_dag_root_init(&prefix, NULL);
rpl_dag_root_init_dag_immediately();
} else {
SHELL_OUTPUT(output, "Node is already a DAG root\n");
}
} else {
if(rpl_dag_root_is_root()) {
SHELL_OUTPUT(output, "Setting as non-root node: leaving DAG\n");
rpl_dag_poison_and_leave();
} else {
SHELL_OUTPUT(output, "Node is not a DAG root\n");
}
}
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static void
shell_output_log_levels(shell_output_func output)
{
int i = 0;
SHELL_OUTPUT(output, "Log levels:\n");
while(all_modules[i].name != NULL) {
SHELL_OUTPUT(output, "-- %-10s: %s\n",
all_modules[i].name,
log_level_to_str(*all_modules[i].curr_log_level));
i++;
}
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_log(struct pt *pt, shell_output_func output, char *args))
{
static int prev_level;
static int level;
char *next_args;
char *ptr;
char *module;
PT_BEGIN(pt);
SHELL_ARGS_INIT(args, next_args);
/* Get and parse argument: module name */
SHELL_ARGS_NEXT(args, next_args);
module = args;
prev_level = log_get_level(module);
if(module == NULL || (strcmp("all", module) && prev_level == -1)) {
SHELL_OUTPUT(output, "Invalid first argument: %s\n", module)
shell_output_log_levels(output);
PT_EXIT(pt);
}
/* Get and parse argument: log level */
SHELL_ARGS_NEXT(args, next_args);
if(args == NULL) {
level = -1;
} else {
level = (int)strtol(args, &ptr, 10);
}
if((level == 0 && args == ptr)
|| level < LOG_LEVEL_NONE || level > LOG_LEVEL_DBG) {
SHELL_OUTPUT(output, "Invalid second argument: %s\n", args);
PT_EXIT(pt);
}
/* Set log level */
if(level != prev_level) {
log_set_level(module, level);
if(!strcmp(module, "mac") || !strcmp(module, "all")) {
if(level >= LOG_LEVEL_DBG) {
tsch_log_init();
SHELL_OUTPUT(output, "TSCH logging started\n");
} else {
tsch_log_stop();
SHELL_OUTPUT(output, "TSCH logging stopped\n");
}
}
}
shell_output_log_levels(output);
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_help(struct pt *pt, shell_output_func output, char *args))
{
struct shell_command_t *cmd_ptr;
PT_BEGIN(pt);
SHELL_OUTPUT(output, "Available commands:\n");
cmd_ptr = shell_commands;
while(cmd_ptr->name != NULL) {
SHELL_OUTPUT(output, "%s\n", cmd_ptr->help);
cmd_ptr++;
}
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_rpl_global_repair(struct pt *pt, shell_output_func output, char *args))
{
PT_BEGIN(pt);
SHELL_OUTPUT(output, "Triggering RPL global repair\n")
rpl_global_repair();
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_rpl_local_repair(struct pt *pt, shell_output_func output, char *args))
{
PT_BEGIN(pt);
SHELL_OUTPUT(output, "Triggering RPL local repair\n");
rpl_local_repair("Shell");
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_ipaddr(struct pt *pt, shell_output_func output, char *args))
{
int i;
uint8_t state;
PT_BEGIN(pt);
SHELL_OUTPUT(output, "Node IPv6 addresses:\n");
for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
state = uip_ds6_if.addr_list[i].state;
if(uip_ds6_if.addr_list[i].isused &&
(state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {
SHELL_OUTPUT(output, "-- ");
shell_output_6addr(output, &uip_ds6_if.addr_list[i].ipaddr);
SHELL_OUTPUT(output, "\n");
}
}
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_ip_neighbors(struct pt *pt, shell_output_func output, char *args))
{
uip_ds6_nbr_t *nbr;
PT_BEGIN(pt);
nbr = uip_ds6_nbr_head();
if(nbr == NULL) {
SHELL_OUTPUT(output, "Node IPv6 neighbors: none\n");
PT_EXIT(pt);
}
SHELL_OUTPUT(output, "Node IPv6 neighbors:\n");
while(nbr != NULL) {
SHELL_OUTPUT(output, "-- ");
shell_output_6addr(output, uip_ds6_nbr_get_ipaddr(nbr));
SHELL_OUTPUT(output, " <-> ");
shell_output_lladdr(output, (linkaddr_t *)uip_ds6_nbr_get_ll(nbr));
SHELL_OUTPUT(output, ", router %u, state %s ",
nbr->isrouter, ds6_nbr_state_to_str(nbr->state));
SHELL_OUTPUT(output, "\n");
nbr = uip_ds6_nbr_next(nbr);
}
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_tsch_status(struct pt *pt, shell_output_func output, char *args))
{
PT_BEGIN(pt);
SHELL_OUTPUT(output, "TSCH status:\n");
SHELL_OUTPUT(output, "-- Is coordinator: %u\n", tsch_is_coordinator);
SHELL_OUTPUT(output, "-- Is associated: %u\n", tsch_is_associated);
if(tsch_is_associated) {
struct tsch_neighbor *n = tsch_queue_get_time_source();
SHELL_OUTPUT(output, "-- PAN ID: 0x%x\n", frame802154_get_pan_id());
SHELL_OUTPUT(output, "-- Is PAN secured: %u\n", tsch_is_pan_secured);
SHELL_OUTPUT(output, "-- Join priority: %u\n", tsch_join_priority);
SHELL_OUTPUT(output, "-- Time source: ");
if(n != NULL) {
shell_output_lladdr(output, &n->addr);
SHELL_OUTPUT(output, "\n");
} else {
SHELL_OUTPUT(output, "none\n");
}
SHELL_OUTPUT(output, "-- Last synchronized: %lu seconds ago\n", (clock_time() - last_sync_time) / CLOCK_SECOND);
SHELL_OUTPUT(output, "-- Drift w.r.t. coordinator: %ld ppm\n", tsch_adaptive_timesync_get_drift_ppm());
}
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_rpl_status(struct pt *pt, shell_output_func output, char *args))
{
PT_BEGIN(pt);
SHELL_OUTPUT(output, "RPL status:\n");
if(!curr_instance.used) {
SHELL_OUTPUT(output, "-- Instance: None\n");
} else {
SHELL_OUTPUT(output, "-- Instance: %u\n", curr_instance.instance_id);
if(rpl_dag_root_is_root()) {
SHELL_OUTPUT(output, "-- DAG root\n");
} else {
SHELL_OUTPUT(output, "-- DAG node\n");
}
SHELL_OUTPUT(output, "-- DAG: ");
shell_output_6addr(output, &curr_instance.dag.dag_id);
SHELL_OUTPUT(output, ", version %u\n", curr_instance.dag.version);
SHELL_OUTPUT(output, "-- Prefix: ");
shell_output_6addr(output, &curr_instance.dag.prefix_info.prefix);
SHELL_OUTPUT(output, "/%u\n", curr_instance.dag.prefix_info.length);
SHELL_OUTPUT(output, "-- MOP: %s\n", rpl_mop_to_str(curr_instance.mop));
SHELL_OUTPUT(output, "-- OF: %s\n", rpl_ocp_to_str(curr_instance.of->ocp));
SHELL_OUTPUT(output, "-- Hop rank increment: %u\n", curr_instance.min_hoprankinc);
SHELL_OUTPUT(output, "-- Default lifetime: %lu seconds\n", RPL_LIFETIME(curr_instance.default_lifetime));
SHELL_OUTPUT(output, "-- State: %s\n", rpl_state_to_str(curr_instance.dag.state));
SHELL_OUTPUT(output, "-- Preferred parent: ");
shell_output_6addr(output, rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent));
SHELL_OUTPUT(output, "\n");
SHELL_OUTPUT(output, "-- Rank: %u\n", curr_instance.dag.rank);
SHELL_OUTPUT(output, "-- Lowest rank: %u (%u)\n", curr_instance.dag.lowest_rank, curr_instance.max_rankinc);
SHELL_OUTPUT(output, "-- DTSN out: %u\n", curr_instance.dtsn_out);
SHELL_OUTPUT(output, "-- DAO sequence: last sent %u, last acked %u\n",
curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_last_acked_seqno);
SHELL_OUTPUT(output, "-- Trickle timer: current %u, min %u, max %u, redundancy %u\n",
curr_instance.dag.dio_intcurrent, curr_instance.dio_intmin,
curr_instance.dio_intmin + curr_instance.dio_intdoubl, curr_instance.dio_redundancy);
}
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args))
{
uip_ds6_defrt_t *default_route;
#if RPL_WITH_NON_STORING
rpl_ns_node_t *link;
#endif /* RPL_WITH_NON_STORING */
#if RPL_WITH_STORING
uip_ds6_route_t *route;
#endif /* RPL_WITH_STORING */
PT_BEGIN(pt);
/* Our default route */
SHELL_OUTPUT(output, "Default route:\n");
default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose());
if(default_route != NULL) {
SHELL_OUTPUT(output, "-- ");
shell_output_6addr(output, &default_route->ipaddr);
if(default_route->lifetime.interval != 0) {
SHELL_OUTPUT(output, " (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval);
} else {
SHELL_OUTPUT(output, " (lifetime: infinite)\n");
}
} else {
SHELL_OUTPUT(output, "-- None\n");
}
#if RPL_WITH_NON_STORING
if(rpl_ns_num_nodes() > 0) {
/* Our routing links */
SHELL_OUTPUT(output, "Routing links (%u in total):\n", rpl_ns_num_nodes());
link = rpl_ns_node_head();
while(link != NULL) {
uip_ipaddr_t child_ipaddr;
uip_ipaddr_t parent_ipaddr;
rpl_ns_get_node_global_addr(&child_ipaddr, link);
rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent);
SHELL_OUTPUT(output, "-- ");
shell_output_6addr(output, &child_ipaddr);
if(link->parent == NULL) {
memset(&parent_ipaddr, 0, sizeof(parent_ipaddr));
SHELL_OUTPUT(output, " (DODAG root)");
} else {
SHELL_OUTPUT(output, " to ");
shell_output_6addr(output, &parent_ipaddr);
}
if(link->lifetime != RPL_ROUTE_INFINITE_LIFETIME) {
SHELL_OUTPUT(output, " (lifetime: %lu seconds)\n", (unsigned long)link->lifetime);
} else {
SHELL_OUTPUT(output, " (lifetime: infinite)\n");
}
link = rpl_ns_node_next(link);
}
} else {
SHELL_OUTPUT(output, "No routing links\n");
}
#endif /* RPL_WITH_NON_STORING */
#if RPL_WITH_STORING
if(uip_ds6_route_num_routes() > 0) {
/* Our routing entries */
SHELL_OUTPUT(output, "Routing entries (%u in total):\n", uip_ds6_route_num_routes());
route = uip_ds6_route_head();
while(route != NULL) {
SHELL_OUTPUT(output, "-- ");
shell_output_6addr(output, &route->ipaddr);
SHELL_OUTPUT(output, " via ");
shell_output_6addr(output, uip_ds6_route_nexthop(route));
if((unsigned long)route->state.lifetime != RPL_ROUTE_INFINITE_LIFETIME) {
SHELL_OUTPUT(output, " (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime);
} else {
SHELL_OUTPUT(output, " (lifetime: infinite)\n");
}
route = uip_ds6_route_next(route);
}
} else {
SHELL_OUTPUT(output, "No routing entries\n");
}
#endif /* RPL_WITH_STORING */
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
static
PT_THREAD(cmd_tsch_schedule(struct pt *pt, shell_output_func output, char *args))
{
struct tsch_slotframe *sf;
PT_BEGIN(pt);
if(tsch_is_locked()) {
PT_EXIT(pt);
}
sf = tsch_schedule_slotframe_head();
if(sf == NULL) {
SHELL_OUTPUT(output, "TSCH schedule: no slotframe\n");
} else {
SHELL_OUTPUT(output, "TSCH schedule:\n");
while(sf != NULL) {
struct tsch_link *l = list_head(sf->links_list);
SHELL_OUTPUT(output, "-- Slotframe: handle %u, size %u, links:\n", sf->handle, sf->size.val);
while(l != NULL) {
SHELL_OUTPUT(output, "---- Options %02x, type %u, timeslot %u, channel offset %u, address ",
l->link_options, l->link_type, l->timeslot, l->channel_offset);
shell_output_lladdr(output, &l->addr);
SHELL_OUTPUT(output, "\n");
l = list_item_next(l);
}
sf = tsch_schedule_slotframe_next(sf);
}
}
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
void
shell_commands_init(void)
{
/* Set up Ping Reply callback */
uip_icmp6_echo_reply_callback_add(&echo_reply_notification,
echo_reply_handler);
}
/*---------------------------------------------------------------------------*/
struct shell_command_t shell_commands[] = {
{ "help", cmd_help, "'> help': Shows this help" },
{ "ip-addr", cmd_ipaddr, "'> ip-addr': Shows all IPv6 addresses" },
{ "ip-nbr", cmd_ip_neighbors, "'> ip-nbr': Shows all IPv6 neighbors" },
{ "log", cmd_log, "'> log module level': Sets log level (0--4) for a given module (or \"all\"). For module \"mac\", level 4 also enables per-slot logging." },
{ "ping", cmd_ping, "'> ping addr': Pings the IPv6 address 'addr'" },
{ "rpl-set-root", cmd_rpl_set_root, "'> rpl-set-root 0/1 [prefix]': Sets node as root (on) or not (off). A /64 prefix can be optionally specified." },
{ "rpl-status", cmd_rpl_status, "'> rpl-status': Shows a summary of the current RPL state" },
{ "rpl-global-repair", cmd_rpl_global_repair, "'> rpl-global-repair': Triggers a RPL global repair" },
{ "rpl-local-repair", cmd_rpl_local_repair, "'> rpl-local-repair': Triggers a RPL local repair" },
{ "routes", cmd_routes, "'> routes': Shows the route entries" },
{ "tsch-schedule", cmd_tsch_schedule, "'> tsch-schedule': Shows the current TSCH schedule" },
{ "tsch-status", cmd_tsch_status, "'> tsch-status': Shows a summary of the current TSCH state" },
{ NULL, NULL, NULL },
};
/** @} */

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2017, Inria.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* Main header file for the Contiki shell
* \author
* Simon Duquennoy <simon.duquennoy@inria.fr>
*/
/** \addtogroup apps
* @{ */
#ifndef _SHELL_COMMANDS_H_
#define _SHELL_COMMANDS_H_
/* Command handling function type */
typedef char (shell_commands_func)(struct pt *pt, shell_output_func output, char *args);
/* Command structure */
struct shell_command_t {
const char *name;
shell_commands_func *func;
const char *help;
};
/* The set of supported commands */
extern struct shell_command_t shell_commands[];
/**
* Initializes Shell-commands module
*/
void shell_commands_init(void);
#endif /* _SHELL_COMMANDS_H_ */
/** @} */

152
apps/shell/shell.c Normal file
View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 2018, Inria.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* The shell application
* \author
* Simon Duquennoy <simon.duquennoy@inria.fr>
*/
/**
* \addtogroup shell
* @{
*/
#include "contiki.h"
#include "shell.h"
#include "shell-commands.h"
#include "net/ip/uip.h"
#include "net/ip/ip64-addr.h"
/*---------------------------------------------------------------------------*/
void
shell_output_6addr(shell_output_func output, const uip_ipaddr_t *ipaddr)
{
uint16_t a;
unsigned int i;
int f;
if(ipaddr == NULL) {
SHELL_OUTPUT(output, "(NULL IP addr)");
return;
}
if(ip64_addr_is_ipv4_mapped_addr(ipaddr)) {
/* Printing IPv4-mapped addresses is done according to RFC 4291 */
SHELL_OUTPUT(output, "::FFFF:%u.%u.%u.%u", ipaddr->u8[12], ipaddr->u8[13], ipaddr->u8[14], ipaddr->u8[15]);
} else {
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
a = (ipaddr->u8[i] << 8) + ipaddr->u8[i + 1];
if(a == 0 && f >= 0) {
if(f++ == 0) {
SHELL_OUTPUT(output, "::");
}
} else {
if(f > 0) {
f = -1;
} else if(i > 0) {
SHELL_OUTPUT(output, ":");
}
SHELL_OUTPUT(output, "%x", a);
}
}
}
}
/*---------------------------------------------------------------------------*/
void
shell_output_lladdr(shell_output_func output, const linkaddr_t *lladdr)
{
if(lladdr == NULL) {
SHELL_OUTPUT(output, "(NULL LL addr)");
return;
} else {
unsigned int i;
for(i = 0; i < LINKADDR_SIZE; i++) {
if(i > 0 && i % 2 == 0) {
SHELL_OUTPUT(output, ".");
}
SHELL_OUTPUT(output, "%02x", lladdr->u8[i]);
}
}
}
/*---------------------------------------------------------------------------*/
static void
output_prompt(shell_output_func output)
{
shell_output_lladdr(output, &linkaddr_node_addr);
SHELL_OUTPUT(output, "> ");
}
/*---------------------------------------------------------------------------*/
PT_THREAD(shell_input(struct pt *pt, shell_output_func output, const char *cmd))
{
static char *args;
static struct shell_command_t *cmd_ptr;
PT_BEGIN(pt);
/* Shave off any leading spaces. */
while(*cmd == ' ') {
cmd++;
}
/* Look for arguments */
args = strchr(cmd, ' ');
if(args != NULL) {
*args = '\0';
args++;
}
/* Lookup for command */
cmd_ptr = shell_commands;
while(cmd_ptr->name != NULL) {
if(strcmp(cmd, cmd_ptr->name) == 0) {
static struct pt cmd_pt;
PT_SPAWN(pt, &cmd_pt, cmd_ptr->func(&cmd_pt, output, args));
goto done;
}
cmd_ptr++;
}
SHELL_OUTPUT(output, "Command not found. Type 'help' for a list of commands\n");
done:
output_prompt(output);
PT_END(pt);
}
/*---------------------------------------------------------------------------*/
void
shell_init(void)
{
shell_commands_init();
}
/** @} */

108
apps/shell/shell.h Normal file
View File

@ -0,0 +1,108 @@
/*
* Copyright (c) 2017, Inria.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*
*/
/**
* \file
* Main header file for the Contiki shell
* \author
* Simon Duquennoy <simon.duquennoy@inria.fr>
*/
/** \addtogroup apps
* @{ */
#ifndef SHELL_H_
#define SHELL_H_
#include "net/ip/uip.h"
#include "net/linkaddr.h"
#include "sys/process.h"
#include <stdio.h>
/* Helper macros to parse arguments */
#define SHELL_ARGS_INIT(args, next_args) (next_args) = (args);
#define SHELL_ARGS_NEXT(args, next_args) do { \
(args) = (next_args); \
if((args) != NULL) { \
if(*(args) == '\0') { \
(args) = NULL; \
} else { \
(next_args) = strchr((args), ' '); \
if((next_args) != NULL) { \
*(next_args) = '\0'; \
(next_args)++; \
} \
} \
} else { \
(next_args) = NULL; \
} \
} while(0)
/* Printf-formatted output via a given output function */
#define SHELL_OUTPUT(output_func, format, ...) do { \
char buffer[128]; \
snprintf(buffer, sizeof(buffer), format, ##__VA_ARGS__); \
(output_func)(buffer); \
} while(0);
typedef void (shell_output_func)(const char *str);
/**
* Initializes Shell module
*/
void shell_init(void);
/**
* \brief A protothread that is spawned by a Shell driver when receiving a new line.
*/
PT_THREAD(shell_input(struct pt *pt, shell_output_func output, const char *cmd));
/**
* Prints an IPv6 address
*
* \param output The output function
* \param ipaddr The IPv6 to printed
*/
void shell_output_6addr(shell_output_func output, const uip_ipaddr_t *ipaddr);
/**
* Prints a link-layer address
*
* \param output The output function
* \param lladdr The link-layer to be printed
*/
void shell_output_lladdr(shell_output_func output, const linkaddr_t *lladdr);
#endif /* SHELL_H_ */
/** @} */

View File

@ -45,6 +45,11 @@ typedef uint32_t rtimer_clock_t;
/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */
#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250))
#define RADIO_DELAY_BEFORE_DETECT 0
#ifndef TSCH_CONF_BASE_DRIFT_PPM
/* The drift compared to "true" 10ms slots.
* Enable adaptive sync to enable compensation for this. */
#define TSCH_CONF_BASE_DRIFT_PPM -977
#endif
/*---------------------------------------------------------------------------*/
/**
* \name Serial Boot Loader Backdoor configuration

View File

@ -92,10 +92,12 @@ vsnprintf(char *str, size_t n, const char *fmt, __VALIST va)
ch = *(fmt++);
lz = 1;
}
if(ch >= '0' && ch <= '9') {
if(ch == '-' || (ch >= '0' && ch <= '9')) {
w = 0;
while(ch >= '0' && ch <= '9') {
w = (((w << 2) + w) << 1) + ch - '0';
while(ch == '-' || (ch >= '0' && ch <= '9')) {
if(ch != '-') {
w = (((w << 2) + w) << 1) + ch - '0';
}
ch = *fmt++;
}
}

View File

@ -84,6 +84,11 @@ typedef uint32_t rtimer_clock_t;
/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */
#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250))
#define RADIO_DELAY_BEFORE_DETECT 0
#ifndef TSCH_CONF_BASE_DRIFT_PPM
/* The drift compared to "true" 10ms slots.
* Enable adaptive sync to enable compensation for this. */
#define TSCH_CONF_BASE_DRIFT_PPM -977
#endif
/*---------------------------------------------------------------------------*/
/**
* \name Serial Boot Loader Backdoor configuration

View File

@ -82,6 +82,11 @@ typedef uint32_t rtimer_clock_t;
/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */
#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250))
#define RADIO_DELAY_BEFORE_DETECT 0
#ifndef TSCH_CONF_BASE_DRIFT_PPM
/* The drift compared to "true" 10ms slots.
* Enable adaptive sync to enable compensation for this. */
#define TSCH_CONF_BASE_DRIFT_PPM -977
#endif
/*---------------------------------------------------------------------------*/
/**
* \name Serial Boot Loader Backdoor configuration

View File

@ -58,7 +58,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "TCP/IP"
#define LOG_LEVEL TCPIP_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_TCPIP
#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN + uip_ext_len])
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
@ -672,6 +672,15 @@ tcpip_ipv6_output(void)
goto send_packet;
}
/* We first check if the destination address is one of ours. There is no
* loopback interface -- instead, process this directly as incoming. */
if(uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr)) {
LOG_INFO("output: sending to ourself\n");
packet_input();
return;
}
/* Look for a next hop */
if((nexthop = get_nexthop(&ipaddr)) == NULL) {
goto exit;
}

View File

@ -81,7 +81,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "6LoWPAN"
#define LOG_LEVEL SICSLOWPAN_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_6LOWPAN
#ifdef SICSLOWPAN_CONF_COMPRESSION
#define SICSLOWPAN_COMPRESSION SICSLOWPAN_CONF_COMPRESSION
@ -1726,6 +1726,11 @@ input(void)
/* The MAC puts the 15.4 payload inside the packetbuf data buffer */
packetbuf_ptr = packetbuf_dataptr();
if(packetbuf_datalen() == 0) {
LOG_WARN("empty packet\n");
return;
}
/* This is default uip_buf since we assume that this is not fragmented */
buffer = (uint8_t *)UIP_IP_BUF;

View File

@ -55,7 +55,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "IPv6 Nbr"
#define LOG_LEVEL IPV6_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_IPV6
#ifdef UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED
#define NEIGHBOR_STATE_CHANGED(n) UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED(n)
@ -161,6 +161,18 @@ uip_ds6_nbr_num(void)
}
/*---------------------------------------------------------------------------*/
uip_ds6_nbr_t *
uip_ds6_nbr_head(void)
{
return nbr_table_head(ds6_neighbors);
}
/*---------------------------------------------------------------------------*/
uip_ds6_nbr_t *
uip_ds6_nbr_next(uip_ds6_nbr_t *nbr)
{
return nbr_table_next(ds6_neighbors, nbr);
}
/*---------------------------------------------------------------------------*/
uip_ds6_nbr_t *
uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
{
uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors);

View File

@ -97,6 +97,8 @@ const uip_lladdr_t *uip_ds6_nbr_lladdr_from_ipaddr(const uip_ipaddr_t *ipaddr);
void uip_ds6_link_callback(int status, int numtx);
void uip_ds6_neighbor_periodic(void);
int uip_ds6_nbr_num(void);
uip_ds6_nbr_t *uip_ds6_nbr_head(void);
uip_ds6_nbr_t *uip_ds6_nbr_next(uip_ds6_nbr_t *nbr);
#if UIP_ND6_SEND_NS
/**

View File

@ -49,7 +49,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "IPv6 Route"
#define LOG_LEVEL IPV6_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_IPV6
/* A configurable function called after adding a new neighbor as next hop */
#ifdef NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK

View File

@ -54,7 +54,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "IPv6 DS"
#define LOG_LEVEL IPV6_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_IPV6
struct etimer uip_ds6_timer_periodic; /**< Timer for maintenance of data structures */

View File

@ -50,7 +50,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "ICMPv6"
#define LOG_LEVEL IPV6_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_IPV6
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
@ -268,6 +268,9 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
void
uip_icmp6_send(const uip_ipaddr_t *dest, int type, int code, int payload_len)
{
LOG_INFO("Sending ICMPv6 packet to ");
LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
LOG_INFO_(", type %u, code %u, len %u\n", type, code, payload_len);
UIP_IP_BUF->vtc = 0x60;
UIP_IP_BUF->tcflow = 0;

View File

@ -78,7 +78,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "IPv6 NDP"
#define LOG_LEVEL IPV6_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_IPV6
/*------------------------------------------------------------------*/
/** @{ */

View File

@ -96,7 +96,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "IPv6"
#define LOG_LEVEL IPV6_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_IPV6
/*---------------------------------------------------------------------------*/
/**

View File

@ -41,7 +41,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "Websocket"
#define LOG_LEVEL IPV6_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_IPV6
enum {
STATE_WAITING_FOR_HEADER,

View File

@ -40,7 +40,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "Websocket"
#define LOG_LEVEL IPV6_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_IPV6
PROCESS(websocket_process, "Websockets process");

View File

@ -58,7 +58,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "CSMA"
#define LOG_LEVEL MAC_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_MAC
/* Constants of the IEEE 802.15.4 standard */

View File

@ -47,7 +47,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "CSMA"
#define LOG_LEVEL MAC_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_MAC
/*---------------------------------------------------------------------------*/
static void

View File

@ -43,7 +43,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "Frame 15.4"
#define LOG_LEVEL FRAMER_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_FRAMER
/* c.f. IEEE 802.15.4e Table 4b */
enum ieee802154e_header_ie_id {

View File

@ -46,7 +46,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "Frame 15.4"
#define LOG_LEVEL FRAMER_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_FRAMER
/** \brief The sequence number (0x00 - 0xff) added to the transmitted
* data or MAC command frame. The default is a random value within

View File

@ -35,7 +35,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "MAC"
#define LOG_LEVEL MAC_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_MAC
/*---------------------------------------------------------------------------*/
void

View File

@ -59,6 +59,12 @@ static uint32_t asn_since_last_learning;
/* Units in which drift is stored: ppm * 256 */
#define TSCH_DRIFT_UNIT (1000L * 1000 * 256)
/*---------------------------------------------------------------------------*/
long int
tsch_adaptive_timesync_get_drift_ppm(void)
{
return (long int)drift_ppm / 256;
}
/*---------------------------------------------------------------------------*/
/* Add a value to a moving average estimator */
static int32_t
@ -101,7 +107,7 @@ timesync_learn_drift_ticks(uint32_t time_delta_asn, int32_t drift_ticks)
TSCH_LOG_ADD(tsch_log_message,
snprintf(log->message, sizeof(log->message),
"drift %ld", (long int)drift_ppm / 256));
"drift %ld", tsch_adaptive_timesync_get_drift_ppm()));
}
/*---------------------------------------------------------------------------*/
/* Either reset or update the neighbor's drift */

View File

@ -86,4 +86,6 @@ void tsch_timesync_update(struct tsch_neighbor *n, uint16_t time_delta_asn, int3
int32_t tsch_timesync_adaptive_compensate(rtimer_clock_t delta_ticks);
long int tsch_adaptive_timesync_get_drift_ppm(void);
#endif /* __TSCH_ADAPTIVE_TIMESYNC_H__ */

View File

@ -63,6 +63,7 @@ PROCESS_NAME(tsch_pending_events_process);
static struct ringbufindex log_ringbuf;
static struct tsch_log_t log_array[TSCH_LOG_QUEUE_LEN];
static int log_dropped = 0;
static int log_active = 0;
/*---------------------------------------------------------------------------*/
/* Process pending log messages */
@ -73,16 +74,16 @@ tsch_log_process_pending(void)
int16_t log_index;
/* Loop on accessing (without removing) a pending input packet */
if(log_dropped != last_log_dropped) {
printf("TSCH:! logs dropped %u\n", log_dropped);
printf("[WARN: TSCH-LOG ] logs dropped %u\n", log_dropped);
last_log_dropped = log_dropped;
}
while((log_index = ringbufindex_peek_get(&log_ringbuf)) != -1) {
struct tsch_log_t *log = &log_array[log_index];
if(log->link == NULL) {
printf("TSCH: {asn-%x.%lx link-NULL} ", log->asn.ms1b, log->asn.ls4b);
printf("[INFO: TSCH-LOG ] {asn-%x.%lx link-NULL} ", log->asn.ms1b, log->asn.ls4b);
} else {
struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle);
printf("TSCH: {asn-%x.%lx link-%u-%u-%u-%u ch-%u} ",
printf("[INFO: TSCH-LOG ] {asn-%x.%lx link-%u-%u-%u-%u ch-%u} ",
log->asn.ms1b, log->asn.ls4b,
log->link->slotframe_handle, sf ? sf->size.val : 0, log->link->timeslot, log->link->channel_offset,
tsch_calculate_channel(&log->asn, log->link->channel_offset));
@ -144,15 +145,30 @@ tsch_log_prepare_add(void)
void
tsch_log_commit(void)
{
ringbufindex_put(&log_ringbuf);
process_poll(&tsch_pending_events_process);
if(log_active == 1) {
ringbufindex_put(&log_ringbuf);
process_poll(&tsch_pending_events_process);
}
}
/*---------------------------------------------------------------------------*/
/* Initialize log module */
void
tsch_log_init(void)
{
ringbufindex_init(&log_ringbuf, TSCH_LOG_QUEUE_LEN);
if(log_active == 0) {
ringbufindex_init(&log_ringbuf, TSCH_LOG_QUEUE_LEN);
log_active = 1;
}
}
/*---------------------------------------------------------------------------*/
/* Stop log module */
void
tsch_log_stop(void)
{
if(log_active == 1) {
tsch_log_process_pending();
log_active = 0;
}
}
#endif /* TSCH_LOG_PER_SLOT */

View File

@ -46,7 +46,7 @@
#define TSCH_LOG_PER_SLOT TSCH_LOG_CONF_PER_SLOT
#else /* TSCH_LOG_CONF_PER_SLOT */
#include "sys/log.h"
#define TSCH_LOG_PER_SLOT (MAC_LOG_LEVEL >= LOG_LEVEL_DBG)
#define TSCH_LOG_PER_SLOT (LOG_LEVEL_MAC >= LOG_LEVEL_DBG)
#endif /* TSCH_LOG_CONF_PER_SLOT */
/* The length of the log queue, i.e. maximum number postponed log messages */
@ -112,6 +112,8 @@ void tsch_log_commit(void);
void tsch_log_init(void);
/* Process pending log messages */
void tsch_log_process_pending(void);
/* Stop logging module */
void tsch_log_stop(void);
/************ Macros **********/

View File

@ -54,7 +54,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "TSCH Pkt"
#define LOG_LEVEL MAC_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_MAC
/*---------------------------------------------------------------------------*/
/* Construct enhanced ACK packet and return ACK length */

View File

@ -58,7 +58,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "TSCH Queue"
#define LOG_LEVEL MAC_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_MAC
/* Check if TSCH_QUEUE_NUM_PER_NEIGHBOR is power of two */
#if (TSCH_QUEUE_NUM_PER_NEIGHBOR & (TSCH_QUEUE_NUM_PER_NEIGHBOR - 1)) != 0

View File

@ -54,7 +54,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "TSCH RPL"
#define LOG_LEVEL MAC_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_MAC
/*---------------------------------------------------------------------------*/
/* To use, set #define TSCH_CALLBACK_KA_SENT tsch_rpl_callback_ka_sent */

View File

@ -58,7 +58,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "TSCH Sched"
#define LOG_LEVEL MAC_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_MAC
/* Pre-allocated space for links */
MEMB(link_memb, struct tsch_link, TSCH_SCHEDULE_MAX_LINKS);
@ -418,6 +418,18 @@ tsch_schedule_create_minimal(void)
0, 0);
}
/*---------------------------------------------------------------------------*/
struct tsch_slotframe *
tsch_schedule_slotframe_head(void)
{
return list_head(slotframe_list);
}
/*---------------------------------------------------------------------------*/
struct tsch_slotframe *
tsch_schedule_slotframe_next(struct tsch_slotframe *sf)
{
return list_item_next(sf);
}
/*---------------------------------------------------------------------------*/
/* Prints out the current schedule (all slotframes and links) */
void
tsch_schedule_print(void)

View File

@ -160,5 +160,8 @@ int tsch_schedule_remove_link_by_timeslot(struct tsch_slotframe *slotframe, uint
/* Returns the next active link after a given ASN, and a backup link (for the same ASN, with Rx flag) */
struct tsch_link * tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset,
struct tsch_link **backup_link);
/* Access to slotframe list */
struct tsch_slotframe *tsch_schedule_slotframe_head(void);
struct tsch_slotframe *tsch_schedule_slotframe_next(struct tsch_slotframe *sf);
#endif /* __TSCH_SCHEDULE_H__ */

View File

@ -134,6 +134,7 @@ struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
/* Last time we received Sync-IE (ACK or data packet from a time source) */
static struct tsch_asn_t last_sync_asn;
clock_time_t last_sync_time; /* Same info, in clock_time_t units */
/* A global lock for manipulating data structures safely from outside of interrupt */
static volatile int tsch_locked = 0;
@ -614,6 +615,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
tsch_timesync_update(current_neighbor, since_last_timesync, drift_correction);
/* Keep track of sync time */
last_sync_asn = tsch_current_asn;
last_sync_time = clock_time();
tsch_schedule_keepalive();
}
mac_tx_status = MAC_TX_OK;
@ -851,6 +853,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
int32_t since_last_timesync = TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn);
/* Keep track of last sync time */
last_sync_asn = tsch_current_asn;
last_sync_time = clock_time();
/* Save estimated drift */
drift_correction = -estimated_drift;
is_drift_correction_used = 1;
@ -1053,6 +1056,7 @@ tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
current_slot_start = next_slot_start;
tsch_current_asn = *next_slot_asn;
last_sync_asn = tsch_current_asn;
last_sync_time = clock_time();
current_link = NULL;
}
/*---------------------------------------------------------------------------*/

View File

@ -103,6 +103,8 @@ extern struct tsch_packet *dequeued_array[TSCH_DEQUEUED_ARRAY_SIZE];
* Will be processed layer by tsch_rx_process_pending */
extern struct ringbufindex input_ringbuf;
extern struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
/* Last clock_time_t where synchronization happened */
extern clock_time_t last_sync_time;
/********** Functions *********/

View File

@ -69,7 +69,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "TSCH"
#define LOG_LEVEL MAC_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_MAC
/* Use to collect link statistics even on Keep-Alive, even though they were
* not sent from an upper layer and don't have a valid packet_sent callback */

View File

@ -107,7 +107,7 @@
#ifdef TSCH_CONF_JOIN_MY_PANID_ONLY
#define TSCH_JOIN_MY_PANID_ONLY TSCH_CONF_JOIN_MY_PANID_ONLY
#else
#define TSCH_JOIN_MY_PANID_ONLY 0
#define TSCH_JOIN_MY_PANID_ONLY 1
#endif
/* The radio polling frequency (in Hz) during association process */

View File

@ -38,7 +38,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
#define RPL_DAG_GRACE_PERIOD (CLOCK_SECOND * 20 * 1)

View File

@ -51,7 +51,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/*---------------------------------------------------------------------------*/
extern rpl_of_t rpl_of0, rpl_mrhof;
@ -88,14 +88,17 @@ rpl_dag_leave(void)
LOG_INFO_(", instance %u\n", curr_instance.instance_id);
/* Issue a no-path DAO */
RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
rpl_icmp6_dao_output(0);
if(!rpl_dag_root_is_root()) {
RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
rpl_icmp6_dao_output(0);
}
/* Forget past link statistics */
link_stats_reset();
/* Remove all neighbors */
/* Remove all neighbors and lnks */
rpl_neighbor_remove_all();
rpl_ns_free_all();
/* Stop all timers */
rpl_timers_stop_dag_timers();
@ -110,6 +113,13 @@ rpl_dag_leave(void)
}
/*---------------------------------------------------------------------------*/
void
rpl_dag_poison_and_leave(void)
{
curr_instance.dag.state = DAG_POISONING;
rpl_timers_schedule_state_update();
}
/*---------------------------------------------------------------------------*/
void
rpl_dag_periodic(unsigned seconds)
{
if(curr_instance.used) {
@ -197,8 +207,10 @@ rpl_local_repair(const char *str)
{
if(curr_instance.used) { /* Check needed because this is a public function */
LOG_WARN("local repair (%s)\n", str);
if(!rpl_dag_root_is_root()) {
curr_instance.dag.state = DAG_INITIALIZED; /* Reset DAG state */
}
curr_instance.of->reset(); /* Reset OF */
curr_instance.dag.state = DAG_INITIALIZED; /* Reset DAG state */
link_stats_reset(); /* Forget past link statistics */
rpl_neighbor_remove_all(); /* Remove all neighbors */
rpl_timers_dio_reset("Local repair"); /* Reset Trickle timer */
@ -220,97 +232,98 @@ rpl_dag_ready_to_advertise(void)
void
rpl_dag_update_state(void)
{
if(curr_instance.used) {
if(!rpl_dag_root_is_root()) {
rpl_nbr_t *old_parent = curr_instance.dag.preferred_parent;
rpl_rank_t old_rank = curr_instance.dag.rank;
rpl_rank_t old_rank;
/* Any scheduled state update is no longer needed */
rpl_timers_unschedule_state_update();
if(!curr_instance.used) {
return;
}
if(curr_instance.dag.state == DAG_POISONING) {
rpl_neighbor_set_preferred_parent(NULL);
curr_instance.dag.rank = RPL_INFINITE_RANK;
if(old_rank != RPL_INFINITE_RANK) {
/* Advertise that we are leaving, and leave after a delay */
LOG_WARN("poisoning and leaving after a delay\n");
rpl_timers_dio_reset("Poison routes");
rpl_timers_schedule_leaving();
old_rank = curr_instance.dag.rank;
/* Any scheduled state update is no longer needed */
rpl_timers_unschedule_state_update();
if(curr_instance.dag.state == DAG_POISONING) {
rpl_neighbor_set_preferred_parent(NULL);
curr_instance.dag.rank = RPL_INFINITE_RANK;
if(old_rank != RPL_INFINITE_RANK) {
/* Advertise that we are leaving, and leave after a delay */
LOG_WARN("poisoning and leaving after a delay\n");
rpl_timers_dio_reset("Poison routes");
rpl_timers_schedule_leaving();
}
} else if(!rpl_dag_root_is_root()) {
rpl_nbr_t *old_parent = curr_instance.dag.preferred_parent;
rpl_nbr_t *nbr;
/* Select and set preferred parent */
rpl_neighbor_set_preferred_parent(rpl_neighbor_select_best());
/* Update rank */
curr_instance.dag.rank = rpl_neighbor_rank_via_nbr(curr_instance.dag.preferred_parent);
/* Update better_parent_since flag for each neighbor */
nbr = nbr_table_head(rpl_neighbors);
while(nbr != NULL) {
if(rpl_neighbor_rank_via_nbr(nbr) < curr_instance.dag.rank) {
/* This neighbor would be a better parent than our current.
Set 'better_parent_since' if not already set. */
if(nbr->better_parent_since == 0) {
nbr->better_parent_since = clock_time(); /* Initialize */
}
} else {
rpl_nbr_t *nbr;
/* Select and set preferred parent */
rpl_neighbor_set_preferred_parent(rpl_neighbor_select_best());
/* Update rank */
curr_instance.dag.rank = rpl_neighbor_rank_via_nbr(curr_instance.dag.preferred_parent);
/* Update better_parent_since flag for each neighbor */
nbr = nbr_table_head(rpl_neighbors);
while(nbr != NULL) {
if(rpl_neighbor_rank_via_nbr(nbr) < curr_instance.dag.rank) {
/* This neighbor would be a better parent than our current.
Set 'better_parent_since' if not already set. */
if(nbr->better_parent_since == 0) {
nbr->better_parent_since = clock_time(); /* Initialize */
}
} else {
nbr->better_parent_since = 0; /* Not a better parent */
}
nbr = nbr_table_next(rpl_neighbors, nbr);
}
if(old_parent == NULL || curr_instance.dag.rank < curr_instance.dag.lowest_rank) {
/* This is a slight departure from RFC6550: if we had no preferred parent before,
* reset lowest_rank. This helps recovering from temporary bad link conditions. */
curr_instance.dag.lowest_rank = curr_instance.dag.rank;
}
/* Reset DIO timer in case of significant rank update */
if(curr_instance.dag.last_advertised_rank != RPL_INFINITE_RANK
&& curr_instance.dag.rank != RPL_INFINITE_RANK
&& ABS((int32_t)curr_instance.dag.rank - curr_instance.dag.last_advertised_rank) > RPL_SIGNIFICANT_CHANGE_THRESHOLD) {
LOG_WARN("significant rank update %u->%u\n",
curr_instance.dag.last_advertised_rank, curr_instance.dag.rank);
/* Update already here to avoid multiple resets in a row */
curr_instance.dag.last_advertised_rank = curr_instance.dag.rank;
rpl_timers_dio_reset("Significant rank update");
}
/* Parent switch */
if(curr_instance.dag.preferred_parent != old_parent) {
/* We just got a parent (was NULL), reset trickle timer to advertise this */
if(old_parent == NULL) {
curr_instance.dag.state = DAG_JOINED;
rpl_timers_dio_reset("Got parent");
LOG_WARN("found parent: ");
LOG_WARN_6ADDR(rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent));
LOG_WARN_(", staying in DAG\n");
rpl_timers_unschedule_leaving();
}
/* Schedule a DAO */
if(curr_instance.dag.preferred_parent != NULL) {
rpl_timers_schedule_dao();
} else {
/* We have no more parent, schedule DIS to get a chance to hear updated state */
curr_instance.dag.state = DAG_INITIALIZED;
LOG_WARN("no parent, scheduling periodic DIS, will leave if no parent is found\n");
rpl_timers_dio_reset("Poison routes");
rpl_timers_schedule_periodic_dis();
rpl_timers_schedule_leaving();
}
#if LOG_INFO_ENABLED
rpl_neighbor_print_list("Parent switch");
#endif /* LOG_INFO_ENABLED */
}
nbr->better_parent_since = 0; /* Not a better parent */
}
nbr = nbr_table_next(rpl_neighbors, nbr);
}
/* Finally, update metric container */
curr_instance.of->update_metric_container();
if(old_parent == NULL || curr_instance.dag.rank < curr_instance.dag.lowest_rank) {
/* This is a slight departure from RFC6550: if we had no preferred parent before,
* reset lowest_rank. This helps recovering from temporary bad link conditions. */
curr_instance.dag.lowest_rank = curr_instance.dag.rank;
}
/* Reset DIO timer in case of significant rank update */
if(curr_instance.dag.last_advertised_rank != RPL_INFINITE_RANK
&& curr_instance.dag.rank != RPL_INFINITE_RANK
&& ABS((int32_t)curr_instance.dag.rank - curr_instance.dag.last_advertised_rank) > RPL_SIGNIFICANT_CHANGE_THRESHOLD) {
LOG_WARN("significant rank update %u->%u\n",
curr_instance.dag.last_advertised_rank, curr_instance.dag.rank);
/* Update already here to avoid multiple resets in a row */
curr_instance.dag.last_advertised_rank = curr_instance.dag.rank;
rpl_timers_dio_reset("Significant rank update");
}
/* Parent switch */
if(curr_instance.dag.preferred_parent != old_parent) {
/* We just got a parent (was NULL), reset trickle timer to advertise this */
if(old_parent == NULL) {
curr_instance.dag.state = DAG_JOINED;
rpl_timers_dio_reset("Got parent");
LOG_WARN("found parent: ");
LOG_WARN_6ADDR(rpl_neighbor_get_ipaddr(curr_instance.dag.preferred_parent));
LOG_WARN_(", staying in DAG\n");
rpl_timers_unschedule_leaving();
}
/* Schedule a DAO */
if(curr_instance.dag.preferred_parent != NULL) {
rpl_timers_schedule_dao();
} else {
/* We have no more parent, schedule DIS to get a chance to hear updated state */
curr_instance.dag.state = DAG_INITIALIZED;
LOG_WARN("no parent, scheduling periodic DIS, will leave if no parent is found\n");
rpl_timers_dio_reset("Poison routes");
rpl_timers_schedule_periodic_dis();
rpl_timers_schedule_leaving();
}
#if LOG_INFO_ENABLED
rpl_neighbor_print_list("Parent switch");
#endif /* LOG_INFO_ENABLED */
}
}
/* Finally, update metric container */
curr_instance.of->update_metric_container();
}
/*---------------------------------------------------------------------------*/
static rpl_nbr_t *
@ -516,8 +529,6 @@ process_dio_init_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
#endif /* RPL_WITH_PROBING */
/* Leave the network after RPL_DELAY_BEFORE_LEAVING in case we do not
find a parent */
rpl_timers_schedule_leaving();
LOG_INFO("initialized DAG with instance ID %u, DAG ID ",
curr_instance.instance_id);
LOG_INFO_6ADDR(&curr_instance.dag.dag_id);
@ -525,6 +536,9 @@ process_dio_init_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
LOG_ANNOTATE("#A init=%u\n", curr_instance.dag.dag_id.u8[sizeof(curr_instance.dag.dag_id) - 1]);
LOG_WARN_("just joined, no parent yet, setting timer for leaving\n");
rpl_timers_schedule_leaving();
return 1;
}
/*---------------------------------------------------------------------------*/

View File

@ -57,6 +57,11 @@
* \return The description string
*/
const char *rpl_dag_state_to_str(enum rpl_dag_state state);
/**
* Start poisoning and leave the DAG after a delay
*
*/
void rpl_dag_poison_and_leave(void);
/**
* Leaves the current DAG
*

View File

@ -51,7 +51,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/*---------------------------------------------------------------------------*/
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
@ -365,14 +365,14 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
uint16_t sender_rank;
uint8_t sender_closer;
rpl_nbr_t *sender;
uint8_t opt_type = UIP_EXT_HDR_OPT_RPL_BUF->opt_type;
uint8_t opt_len = UIP_EXT_HDR_OPT_RPL_BUF->opt_len;
if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
|| UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL
|| UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
|| opt_type != UIP_EXT_HDR_OPT_RPL
|| opt_len != RPL_HDR_OPT_LEN) {
LOG_ERR("hop-by-hop extension header has wrong size or type (%u %u %u)\n",
UIP_HBHO_BUF->len, UIP_EXT_HDR_OPT_RPL_BUF->opt_type,
UIP_EXT_HDR_OPT_RPL_BUF->opt_len);
UIP_HBHO_BUF->len, opt_type, opt_len);
return 0; /* Drop */
}

View File

@ -56,7 +56,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/*---------------------------------------------------------------------------*/
#define RPL_DIO_GROUNDED 0x80
@ -557,10 +557,19 @@ rpl_icmp6_dao_output(uint8_t lifetime)
/* Make sure we're up-to-date before sending data out */
rpl_dag_update_state();
if(!curr_instance.used || curr_instance.dag.preferred_parent == NULL
|| prefix == NULL || parent_ipaddr == NULL || curr_instance.mop == RPL_MOP_NO_DOWNWARD_ROUTES) {
LOG_WARN("rpl_icmp6_dao_output: node not ready to send a DAO (used %u, pref parent %u, prefix %u, mop %u)\n",
curr_instance.used, curr_instance.dag.preferred_parent != NULL && parent_ipaddr != NULL, prefix != NULL, curr_instance.mop);
if(!curr_instance.used) {
LOG_WARN("rpl_icmp6_dao_output: not in an instance, skip sending DAO\n");
return;
}
if(curr_instance.dag.preferred_parent == NULL) {
LOG_WARN("rpl_icmp6_dao_output: no preferred parent, skip sending DAO\n");
return;
}
if(prefix == NULL || parent_ipaddr == NULL || curr_instance.mop == RPL_MOP_NO_DOWNWARD_ROUTES) {
LOG_WARN("rpl_icmp6_dao_output: node not ready to send a DAO (prefix %p, parent addr %p, mop %u)\n",
prefix, parent_ipaddr, curr_instance.mop);
return;
}

View File

@ -54,7 +54,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/* RFC6551 and RFC6719 do not mandate the use of a specific formula to
* compute the ETX value. This MRHOF implementation relies on the value

View File

@ -50,7 +50,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/*
* Policy for neighbor addition

View File

@ -51,7 +51,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/* A configurable function called after every RPL parent switch */
#ifdef RPL_CALLBACK_PARENT_SWITCH

View File

@ -44,7 +44,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/* Total number of nodes */
static int num_nodes;
@ -203,6 +203,7 @@ void
rpl_ns_periodic(unsigned seconds)
{
rpl_ns_node_t *l;
rpl_ns_node_t *next;
/* First pass, decrement lifetime for all nodes with non-infinite lifetime */
for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) {
/* Don't touch infinite lifetime nodes */
@ -211,7 +212,8 @@ rpl_ns_periodic(unsigned seconds)
}
}
/* Second pass, for all expired nodes, deallocate them iff no child points to them */
for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) {
for(l = list_head(nodelist); l != NULL; l = next) {
next = list_item_next(l);
if(l->lifetime == 0) {
rpl_ns_node_t *l2;
for(l2 = list_head(nodelist); l2 != NULL; l2 = list_item_next(l2)) {
@ -233,3 +235,16 @@ rpl_ns_periodic(unsigned seconds)
}
}
}
/*---------------------------------------------------------------------------*/
void
rpl_ns_free_all(void)
{
rpl_ns_node_t *l;
rpl_ns_node_t *next;
for(l = list_head(nodelist); l != NULL; l = next) {
next = list_item_next(l);
list_remove(nodelist, l);
memb_free(&nodememb, l);
num_nodes--;
}
}

View File

@ -144,6 +144,11 @@ void rpl_ns_periodic(unsigned seconds);
*/
void rpl_ns_init(void);
/**
* Deallocate all neighbors
*/
void rpl_ns_free_all(void);
/** @} */
#endif /* RPL_NS_H */

View File

@ -50,7 +50,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/* Constants from RFC6552. We use the default values. */
#define RANK_STRETCH 0 /* Must be in the range [0;5] */

View File

@ -51,7 +51,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
/* A configurable function called after update of the RPL DIO interval */
#ifdef RPL_CALLBACK_NEW_DIO_INTERVAL
@ -483,7 +483,7 @@ rpl_timers_schedule_leaving(void)
{
if(curr_instance.used) {
if(ctimer_expired(&curr_instance.dag.leave)) {
ctimer_set(&curr_instance.dag.leave, PERIODIC_DELAY, handle_leaving_timer, NULL);
ctimer_set(&curr_instance.dag.leave, RPL_DELAY_BEFORE_LEAVING, handle_leaving_timer, NULL);
}
}
}

View File

@ -48,7 +48,7 @@
/* Log configuration */
#include "sys/log.h"
#define LOG_MODULE "RPL"
#define LOG_LEVEL RPL_LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_RPL
uip_ipaddr_t rpl_multicast_addr;

View File

@ -78,29 +78,29 @@
/********************* A list of currently supported modules ******************/
/******************************************************************************/
#ifndef RPL_LOG_LEVEL
#define RPL_LOG_LEVEL LOG_LEVEL_NONE /* Only for rpl-lite */
#endif /* RPL_LOG_LEVEL */
#ifndef LOG_CONF_LEVEL_RPL
#define LOG_CONF_LEVEL_RPL LOG_LEVEL_NONE /* Only for rpl-lite */
#endif /* LOG_CONF_LEVEL_RPL */
#ifndef TCPIP_LOG_LEVEL
#define TCPIP_LOG_LEVEL LOG_LEVEL_NONE
#endif /* TCPIP_LOG_LEVEL */
#ifndef LOG_CONF_LEVEL_TCPIP
#define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_NONE
#endif /* LOG_CONF_LEVEL_TCPIP */
#ifndef IPV6_LOG_LEVEL
#define IPV6_LOG_LEVEL LOG_LEVEL_NONE
#endif /* IPV6_LOG_LEVEL */
#ifndef LOG_CONF_LEVEL_IPV6
#define LOG_CONF_LEVEL_IPV6 LOG_LEVEL_NONE
#endif /* LOG_CONF_LEVEL_IPV6 */
#ifndef SICSLOWPAN_LOG_LEVEL
#define SICSLOWPAN_LOG_LEVEL LOG_LEVEL_NONE
#endif /* SICSLOWPAN_LOG_LEVEL */
#ifndef LOG_CONF_LEVEL_6LOWPAN
#define LOG_CONF_LEVEL_6LOWPAN LOG_LEVEL_NONE
#endif /* LOG_CONF_LEVEL_6LOWPAN */
#ifndef MAC_LOG_LEVEL
#define MAC_LOG_LEVEL LOG_LEVEL_NONE
#endif /* MAC_LOG_LEVELL */
#ifndef LOG_CONF_LEVEL_MAC
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_NONE
#endif /* LOG_CONF_LEVEL_MAC */
#ifndef FRAMER_LOG_LEVEL
#define FRAMER_LOG_LEVEL LOG_LEVEL_NONE
#endif /* FRAMER_LOG_LEVEL */
#ifndef LOG_CONF_LEVEL_FRAMER
#define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_NONE
#endif /* LOG_CONF_LEVEL_FRAMER */
#endif /* __LOG_CONF_H__ */

View File

@ -53,6 +53,24 @@
#include "sys/log.h"
#include "net/ip/ip64-addr.h"
int curr_log_level_rpl = LOG_CONF_LEVEL_RPL;
int curr_log_level_tcpip = LOG_CONF_LEVEL_TCPIP;
int curr_log_level_ipv6 = LOG_CONF_LEVEL_IPV6;
int curr_log_level_6lowpan = LOG_CONF_LEVEL_6LOWPAN;
int curr_log_level_mac = LOG_CONF_LEVEL_MAC;
int curr_log_level_framer = LOG_CONF_LEVEL_FRAMER;
struct log_module all_modules[] = {
{"rpl", &curr_log_level_rpl, LOG_CONF_LEVEL_RPL},
{"tcpip", &curr_log_level_tcpip, LOG_CONF_LEVEL_TCPIP},
{"ipv6", &curr_log_level_ipv6, LOG_CONF_LEVEL_IPV6},
{"6lowpan", &curr_log_level_6lowpan, LOG_CONF_LEVEL_6LOWPAN},
{"mac", &curr_log_level_mac, LOG_CONF_LEVEL_MAC},
{"framer", &curr_log_level_framer, LOG_CONF_LEVEL_FRAMER},
{NULL, NULL, 0},
};
/*---------------------------------------------------------------------------*/
void
log_6addr(const uip_ipaddr_t *ipaddr)
@ -131,6 +149,52 @@ log_lladdr_compact(const linkaddr_t *lladdr)
LOG_OUTPUT("LL-%04x", UIP_HTONS(lladdr->u16[LINKADDR_SIZE/2-1]));
}
}
/*---------------------------------------------------------------------------*/
void
log_set_level(const char *module, int level)
{
if(level >= LOG_LEVEL_NONE && level <= LOG_LEVEL_DBG) {
int i = 0;
int module_all = !strcmp("all", module);
while(all_modules[i].name != NULL) {
if(module_all || !strcmp(module, all_modules[i].name)) {
*all_modules[i].curr_log_level = MIN(level, all_modules[i].max_log_level);
}
i++;
}
}
}
/*---------------------------------------------------------------------------*/
int
log_get_level(const char *module)
{
int i = 0;
while(all_modules[i].name != NULL) {
if(!strcmp(module, all_modules[i].name)) {
return *all_modules[i].curr_log_level;
}
i++;
}
return -1;
}
/*---------------------------------------------------------------------------*/
const char *
log_level_to_str(int level)
{
switch(level) {
case LOG_LEVEL_NONE:
return "None";
case LOG_LEVEL_ERR:
return "Errors";
case LOG_LEVEL_WARN:
return "Warnings";
case LOG_LEVEL_INFO:
return "Info";
case LOG_LEVEL_DBG:
return "Debug";
default:
return "N/A";
}
}
/** @} */
/** @} */

View File

@ -65,10 +65,34 @@
#define LOG_LEVEL_INFO 3 /* Basic info */
#define LOG_LEVEL_DBG 4 /* Detailled debug */
/* Per-module log level */
struct log_module {
const char *name;
int *curr_log_level;
int max_log_level;
};
extern int curr_log_level_rpl;
extern int curr_log_level_tcpip;
extern int curr_log_level_ipv6;
extern int curr_log_level_6lowpan;
extern int curr_log_level_mac;
extern int curr_log_level_framer;
extern struct log_module all_modules[];
#define LOG_LEVEL_RPL MIN((LOG_CONF_LEVEL_RPL), curr_log_level_rpl)
#define LOG_LEVEL_TCPIP MIN((LOG_CONF_LEVEL_TCPIP), curr_log_level_tcpip)
#define LOG_LEVEL_IPV6 MIN((LOG_CONF_LEVEL_IPV6), curr_log_level_ipv6)
#define LOG_LEVEL_6LOWPAN MIN((LOG_CONF_LEVEL_6LOWPAN), curr_log_level_6lowpan)
#define LOG_LEVEL_MAC MIN((LOG_CONF_LEVEL_MAC), curr_log_level_mac)
#define LOG_LEVEL_FRAMER MIN((LOG_CONF_LEVEL_FRAMER), curr_log_level_framer)
/* Main log function */
#define LOG(newline, level, levelstr, ...) do { \
if(level <= LOG_LEVEL) { \
if(level <= (LOG_LEVEL)) { \
if(newline) { \
LOG_OUTPUT("[%-4s: %-10s] ", levelstr, LOG_MODULE); \
if(LOG_WITH_LOC) { \
@ -88,7 +112,7 @@
/* Link-layer address */
#define LOG_LLADDR(level, lladdr) do { \
if(level <= LOG_LEVEL) { \
if(level <= (LOG_LEVEL)) { \
if(LOG_WITH_COMPACT_ADDR) { \
log_lladdr_compact(lladdr); \
} else { \
@ -99,7 +123,7 @@
/* IPv6 address */
#define LOG_6ADDR(level, ipaddr) do { \
if(level <= LOG_LEVEL) { \
if(level <= (LOG_LEVEL)) { \
if(LOG_WITH_COMPACT_ADDR) { \
log_6addr_compact(ipaddr); \
} else { \
@ -130,11 +154,10 @@
#define LOG_DBG_6ADDR(...) LOG_6ADDR(LOG_LEVEL_DBG, __VA_ARGS__)
/* For testing log level */
#define LOG_ERR_ENABLED (LOG_LEVEL >= LOG_LEVEL_ERR)
#define LOG_WARN_ENABLED (LOG_LEVEL >= LOG_LEVEL_WARN)
#define LOG_INFO_ENABLED (LOG_LEVEL >= LOG_LEVEL_INFO)
#define LOG_DBG_ENABLED (LOG_LEVEL >= LOG_LEVEL_DBG)
#define LOG_ANNOTATE_ENABLED (LOG_LEVEL >= LOG_LEVEL_ANNOTATE)
#define LOG_ERR_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_ERR)
#define LOG_WARN_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_WARN)
#define LOG_INFO_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_INFO)
#define LOG_DBG_ENABLED (MIN(LOG_LEVEL, curr_log_level) >= LOG_LEVEL_DBG)
#if NETSTACK_CONF_WITH_IPV6
@ -164,6 +187,29 @@ void log_lladdr(const linkaddr_t *lladdr);
*/
void log_lladdr_compact(const linkaddr_t *lladdr);
/**
* Sets a log level at run-time. Logs are included in the firmware via
* the compile-time flags in log-conf.h, but this allows to force lower log
* levels, system-wide.
* \param module The target module string descriptor
* \param level The log level
*/
void log_set_level(const char *module, int level);
/**
* Returns the current log level.
* \param module The target module string descriptor
* \return The current log level
*/
int log_get_level(const char *module);
/**
* Returns a textual description of a log level
* \param level log level
* \return The textual description
*/
const char *log_level_to_str(int level);
#endif /* __LOG_H__ */
/** @} */

View File

@ -7,8 +7,9 @@ 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
MAKE_WITH_PERIODIC_ROUTES_PRINT ?= 0 # print #routes periodically, used for regression tests
APPS += orchestra
APPS += orchestra shell
MODULES += core/net/mac/tsch
ifeq ($(MAKE_WITH_ORCHESTRA),1)
@ -19,4 +20,8 @@ ifeq ($(MAKE_WITH_SECURITY),1)
CFLAGS += -DWITH_SECURITY=1
endif
ifeq ($(MAKE_WITH_PERIODIC_ROUTES_PRINT),1)
CFLAGS += -DWITH_PERIODIC_ROUTES_PRINT=1
endif
include $(CONTIKI)/Makefile.include

View File

@ -40,205 +40,73 @@
#include "node-id.h"
#include "rpl.h"
#include "rpl-dag-root.h"
#include "sys/log.h"
#include "net/ipv6/uip-ds6-route.h"
#include "net/mac/tsch/tsch.h"
#include "net/mac/tsch/tsch-log.h"
#if UIP_CONF_IPV6_RPL_LITE == 0
#include "rpl-private.h"
#endif /* UIP_CONF_IPV6_RPL_LITE == 0 */
#if WITH_ORCHESTRA
#include "orchestra.h"
#endif /* WITH_ORCHESTRA */
#if WITH_SHELL
#include "serial-shell.h"
#endif /* WITH_SHELL */
#define DEBUG DEBUG_PRINT
#include "net/ip/uip-debug.h"
#define CONFIG_VIA_BUTTON PLATFORM_HAS_BUTTON
#if CONFIG_VIA_BUTTON
#include "button-sensor.h"
#endif /* CONFIG_VIA_BUTTON */
/*---------------------------------------------------------------------------*/
PROCESS(node_process, "RPL Node");
#if CONFIG_VIA_BUTTON
AUTOSTART_PROCESSES(&node_process, &sensors_process);
#else /* CONFIG_VIA_BUTTON */
AUTOSTART_PROCESSES(&node_process);
#endif /* CONFIG_VIA_BUTTON */
/*---------------------------------------------------------------------------*/
static void
print_network_status(void)
{
int i;
uint8_t state;
uip_ds6_defrt_t *default_route;
#if RPL_WITH_STORING
uip_ds6_route_t *route;
#endif /* RPL_WITH_STORING */
#if RPL_WITH_NON_STORING
rpl_ns_node_t *link;
#endif /* RPL_WITH_NON_STORING */
PRINTF("--- Network status ---\n");
/* Our IPv6 addresses */
PRINTF("- Server IPv6 addresses:\n");
for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
state = uip_ds6_if.addr_list[i].state;
if(uip_ds6_if.addr_list[i].isused &&
(state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {
PRINTF("-- ");
PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr);
PRINTF("\n");
}
}
/* Our default route */
PRINTF("- Default route:\n");
default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose());
if(default_route != NULL) {
PRINTF("-- ");
PRINT6ADDR(&default_route->ipaddr);
PRINTF(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval);
} else {
PRINTF("-- None\n");
}
#if RPL_WITH_STORING
/* Our routing entries */
PRINTF("- Routing entries (%u in total):\n", uip_ds6_route_num_routes());
route = uip_ds6_route_head();
while(route != NULL) {
PRINTF("-- ");
PRINT6ADDR(&route->ipaddr);
PRINTF(" via ");
PRINT6ADDR(uip_ds6_route_nexthop(route));
PRINTF(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime);
route = uip_ds6_route_next(route);
}
#endif
#if RPL_WITH_NON_STORING
/* Our routing links */
PRINTF("- Routing links (%u in total):\n", rpl_ns_num_nodes());
link = rpl_ns_node_head();
while(link != NULL) {
uip_ipaddr_t child_ipaddr;
uip_ipaddr_t parent_ipaddr;
rpl_ns_get_node_global_addr(&child_ipaddr, link);
rpl_ns_get_node_global_addr(&parent_ipaddr, link->parent);
PRINTF("-- ");
PRINT6ADDR(&child_ipaddr);
if(link->parent == NULL) {
memset(&parent_ipaddr, 0, sizeof(parent_ipaddr));
PRINTF(" --- DODAG root ");
} else {
PRINTF(" to ");
PRINT6ADDR(&parent_ipaddr);
}
PRINTF(" (lifetime: %lu seconds)\n", (unsigned long)link->lifetime);
link = rpl_ns_node_next(link);
}
#endif
PRINTF("----------------------\n");
}
/*---------------------------------------------------------------------------*/
static void
net_init(uip_ipaddr_t *br_prefix)
{
if(br_prefix) { /* We are RPL root. Will be set automatically
as TSCH pan coordinator via the tsch-rpl module */
rpl_dag_root_init(br_prefix, NULL);
rpl_dag_root_init_dag_immediately();
} else {
rpl_dag_root_init(NULL, NULL);
}
NETSTACK_MAC.on();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(node_process, ev, data)
{
static struct etimer et;
int is_coordinator;
PROCESS_BEGIN();
/* 3 possible roles:
* - role_6ln: simple node, will join any network, secured or not
* - role_6dr: DAG root, will advertise (unsecured) beacons
* - role_6dr_sec: DAG root, will advertise secured beacons
* */
static int is_coordinator = 0;
static enum { role_6ln, role_6dr, role_6dr_sec } node_role;
node_role = role_6ln;
is_coordinator = 0;
int coordinator_candidate = 0;
#if WITH_SHELL
serial_shell_init();
log_set_level("all", LOG_LEVEL_WARN);
tsch_log_stop();
#endif /* WITH_SHELL */
#if CONTIKI_TARGET_COOJA
coordinator_candidate = (node_id == 1);
is_coordinator = (node_id == 1);
#endif
if(coordinator_candidate) {
if(LLSEC802154_ENABLED) {
node_role = role_6dr_sec;
} else {
node_role = role_6dr;
}
} else {
node_role = role_6ln;
}
#if CONFIG_VIA_BUTTON
{
#define CONFIG_WAIT_TIME 5
SENSORS_ACTIVATE(button_sensor);
etimer_set(&et, CLOCK_SECOND * CONFIG_WAIT_TIME);
while(!etimer_expired(&et)) {
printf("Init: current role: %s. Will start in %u seconds. Press user button to toggle mode.\n",
node_role == role_6ln ? "6ln" : (node_role == role_6dr) ? "6dr" : "6dr-sec",
CONFIG_WAIT_TIME);
PROCESS_WAIT_EVENT_UNTIL(((ev == sensors_event) &&
(data == &button_sensor) && button_sensor.value(0) > 0)
|| etimer_expired(&et));
if(ev == sensors_event && data == &button_sensor && button_sensor.value(0) > 0) {
node_role = (node_role + 1) % 3;
if(LLSEC802154_ENABLED == 0 && node_role == role_6dr_sec) {
node_role = (node_role + 1) % 3;
}
etimer_restart(&et);
}
}
}
#endif /* CONFIG_VIA_BUTTON */
printf("Init: node starting with role %s\n",
node_role == role_6ln ? "6ln" : (node_role == role_6dr) ? "6dr" : "6dr-sec");
tsch_set_pan_secured(LLSEC802154_ENABLED && (node_role == role_6dr_sec));
is_coordinator = node_role > role_6ln;
if(is_coordinator) {
uip_ipaddr_t prefix;
uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
net_init(&prefix);
} else {
net_init(NULL);
rpl_dag_root_init_dag_immediately();
}
NETSTACK_MAC.on();
#if WITH_ORCHESTRA
orchestra_init();
#endif /* WITH_ORCHESTRA */
/* Print out routing tables every minute */
etimer_set(&et, CLOCK_SECOND * 60);
while(1) {
print_network_status();
PROCESS_YIELD_UNTIL(etimer_expired(&et));
etimer_reset(&et);
#if WITH_PERIODIC_ROUTES_PRINT
{
static struct etimer et;
/* Print out routing tables every minute */
etimer_set(&et, CLOCK_SECOND * 60);
while(1) {
/* Used for non-regression testing */
#if RPL_WITH_STORING
PRINTF("Routing entries: %u\n", uip_ds6_route_num_routes());
#endif
#if RPL_WITH_NON_STORING
PRINTF("Routing links: %u\n", rpl_ns_num_nodes());
#endif
PROCESS_YIELD_UNTIL(etimer_expired(&et));
etimer_reset(&et);
}
}
#endif /* WITH_PERIODIC_ROUTES_PRINT */
PROCESS_END();
}

View File

@ -35,6 +35,9 @@
#ifndef __PROJECT_CONF_H__
#define __PROJECT_CONF_H__
/* Set to use the Contiki shell */
#define WITH_SHELL 1
/* Set to run orchestra */
#ifndef WITH_ORCHESTRA
#define WITH_ORCHESTRA 0
@ -75,6 +78,18 @@
#undef SYS_CTRL_CONF_OSC32K_USE_XTAL
#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1
#if WITH_SHELL
/* Needed for CC2538 platforms, for serial */
#define USB_SERIAL_CONF_ENABLE 1
/* USB serial takes space, free more space elsewhere */
#undef SICSLOWPAN_CONF_FRAG
#define SICSLOWPAN_CONF_FRAG 0
#undef UIP_CONF_BUFFER_SIZE
#define UIP_CONF_BUFFER_SIZE 160
#endif /* WITH_SHELL */
/* Needed for cc2420 platforms only */
/* Disable DCO calibration (uses timerB) */
#undef DCOSYNCH_CONF_ENABLED
@ -87,13 +102,9 @@
/******************* Configure TSCH ********************/
/*******************************************************/
/* TSCH per-slot logging */
#undef TSCH_LOG_CONF_PER_SLOT
#define TSCH_LOG_CONF_PER_SLOT 1
/* IEEE802.15.4 PANID */
#undef IEEE802154_CONF_PANID
#define IEEE802154_CONF_PANID 0xabcd
#define IEEE802154_CONF_PANID 0x81a5
/* Do not start TSCH at init, wait for NETSTACK_MAC.on() */
#undef TSCH_CONF_AUTOSTART
@ -145,4 +156,13 @@
#define TSCH_CONF_MAX_EB_PERIOD (4 * CLOCK_SECOND)
#endif /* CONTIKI_TARGET_COOJA */
/* Logging */
#define LOG_CONF_LEVEL_RPL LOG_LEVEL_INFO
#define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_IPV6 LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_6LOWPAN LOG_LEVEL_WARN
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_INFO
#define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_DBG
#define TSCH_LOG_CONF_PER_SLOT 1
#endif /* __PROJECT_CONF_H__ */

View File

@ -39,11 +39,12 @@
* LOG_LEVEL_INFO Basic info
* LOG_LEVEL_DBG Detailled debug
*/
#define IPV6_LOG_LEVEL LOG_LEVEL_DBG
#define SICSLOWPAN_LOG_LEVEL LOG_LEVEL_DBG
#define TCPIP_LOG_LEVEL LOG_LEVEL_DBG
#define MAC_LOG_LEVEL LOG_LEVEL_DBG
#define FRAMER_LOG_LEVEL LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_IPV6 LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_RPL LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_6LOWPAN LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_TCPIP LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_MAC LOG_LEVEL_DBG
#define LOG_CONF_LEVEL_FRAMER LOG_LEVEL_DBG
/* Enable cooja annotations */
#define LOG_CONF_WITH_ANNOTATE 1

View File

@ -26,7 +26,7 @@
<description>Cooja Mote Type #mtype1</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/rpl-tsch/node.c</source>
<commands EXPORT="discard">make TARGET=cooja clean
make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=0</commands>
make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
@ -278,7 +278,7 @@ log.log("Waiting for routing links to fill\n");&#xD;
while(true) {;&#xD;
WAIT_UNTIL(id == 1 &amp;&amp; msg.contains("Routing links"));&#xD;
log.log(msg + "\n");&#xD;
if(msg.contains("Routing links (9 in total):")) {&#xD;
if(msg.contains("Routing links: 9")) {&#xD;
log.testOK(); /* Report test success and quit */&#xD;
}&#xD;
YIELD();&#xD;

View File

@ -26,7 +26,7 @@
<description>Cooja Mote Type #mtype11</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/rpl-tsch/node.c</source>
<commands EXPORT="discard">make TARGET=cooja clean
make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=1 MAKE_WITH_SECURITY=0</commands>
make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=1 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands>
<firmware
EXPORT="copy">[CONTIKI_DIR]/examples/ipv6/rpl-tsch/node.mtype1</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
@ -280,7 +280,7 @@ log.log("Waiting for routing links to fill\n");&#xD;
while(true) {;&#xD;
WAIT_UNTIL(id == 1 &amp;&amp; msg.contains("Routing links"));&#xD;
log.log(msg + "\n");&#xD;
if(msg.contains("Routing links (9 in total):")) {&#xD;
if(msg.contains("Routing links: 9")) {&#xD;
log.testOK(); /* Report test success and quit */&#xD;
}&#xD;
YIELD();&#xD;

View File

@ -26,7 +26,7 @@
<description>Cooja Mote Type #mtype11</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/rpl-tsch/node.c</source>
<commands EXPORT="discard">make TARGET=cooja clean
make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=1</commands>
make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=1 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
@ -278,7 +278,7 @@ log.log("Waiting for routing links to fill\n");&#xD;
while(true) {;&#xD;
WAIT_UNTIL(id == 1 &amp;&amp; msg.contains("Routing links"));&#xD;
log.log(msg + "\n");&#xD;
if(msg.contains("Routing links (9 in total):")) {&#xD;
if(msg.contains("Routing links: 9")) {&#xD;
log.testOK(); /* Report test success and quit */&#xD;
}&#xD;
YIELD();&#xD;

Binary file not shown.

Binary file not shown.