From 12d976f7b5c8b644f58bff9af6c2d299c0887f1b Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Thu, 6 Jul 2017 19:24:27 +0200 Subject: [PATCH 01/21] Emulate loopback: when sending an IP packet to one of our addresses, process it directly as input --- core/net/ip/tcpip.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/net/ip/tcpip.c b/core/net/ip/tcpip.c index bf6d328e4..35600e7c6 100644 --- a/core/net/ip/tcpip.c +++ b/core/net/ip/tcpip.c @@ -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; } From 801fb2373ac39404eaf7ea950ed605e0d80d00ed Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Thu, 6 Jul 2017 19:24:47 +0200 Subject: [PATCH 02/21] Added missing LOG in uip-icmp6 --- core/net/ipv6/uip-icmp6.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/net/ipv6/uip-icmp6.c b/core/net/ipv6/uip-icmp6.c index 9e28abc92..a9ec6be6b 100644 --- a/core/net/ipv6/uip-icmp6.c +++ b/core/net/ipv6/uip-icmp6.c @@ -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; From ad6ef11a0b0815e4c6ff0a08a048cc199490b09e Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Thu, 6 Jul 2017 19:29:42 +0200 Subject: [PATCH 03/21] Added new shell --- apps/shell/serial-shell.c | 81 +++++++++++++++++++ apps/shell/serial-shell.h | 49 ++++++++++++ apps/shell/shell-commands.c | 141 +++++++++++++++++++++++++++++++++ apps/shell/shell-commands.h | 66 ++++++++++++++++ apps/shell/shell.c | 152 ++++++++++++++++++++++++++++++++++++ apps/shell/shell.h | 88 +++++++++++++++++++++ 6 files changed, 577 insertions(+) create mode 100644 apps/shell/serial-shell.c create mode 100644 apps/shell/serial-shell.h create mode 100644 apps/shell/shell-commands.c create mode 100644 apps/shell/shell-commands.h create mode 100644 apps/shell/shell.c create mode 100644 apps/shell/shell.h diff --git a/apps/shell/serial-shell.c b/apps/shell/serial-shell.c new file mode 100644 index 000000000..c2f389515 --- /dev/null +++ b/apps/shell/serial-shell.c @@ -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 + * Simon Duquennoy + */ + +/** + * \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); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/apps/shell/serial-shell.h b/apps/shell/serial-shell.h new file mode 100644 index 000000000..2c364922c --- /dev/null +++ b/apps/shell/serial-shell.h @@ -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 + * Simon Duquennoy + */ + +#ifndef SERIAL_SHELL_H_ +#define SERIAL_SHELL_H_ + +/** + * Initializes Serial Shell module + */ +void serial_shell_init(void); + +#endif /* SERIAL_SHELL_H_ */ diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c new file mode 100644 index 000000000..611335c5f --- /dev/null +++ b/apps/shell/shell-commands.c @@ -0,0 +1,141 @@ +/* + * 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 + */ + +/** + * \addtogroup shell + * @{ + */ + +#include "contiki.h" +#include "shell.h" +#include "shell-commands.h" +#include "net/ip/uip.h" +#include "net/ip/uiplib.h" +#include "net/ipv6/uip-icmp6.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 void +echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen) +{ + if(curr_ping_output_func != NULL) { + SHELL_OUTPUT(curr_ping_output_func, "Received ping reply from "); + shell_output_6addr(curr_ping_output_func, source); + SHELL_OUTPUT(curr_ping_output_func, ", ttl %u, len %u\n", ttl, datalen); + curr_ping_output_func = NULL; + process_poll(curr_ping_process); + } +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, const char *args)) +{ + static uip_ipaddr_t remote_addr; + static char *next_args; + static struct etimer timeout_timer; + + PT_BEGIN(pt); + + /* Isolate first argument */ + next_args = strchr(args, ' '); + if(next_args != NULL) { + *next_args = '\0'; + 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; + } + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(cmd_help(struct pt *pt, shell_output_func output, const char *args)) +{ + PT_BEGIN(pt); + + struct shell_command_t *cmd_ptr = shell_commands; + + SHELL_OUTPUT(output, "Available commands:\n"); + while(cmd_ptr->name != NULL) { + SHELL_OUTPUT(output, "%s\n", cmd_ptr->help); + cmd_ptr++; + } + + 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" }, + { "ping", cmd_ping, "'> ping addr': Pings the IPv6 address 'addr'" }, + { NULL, NULL, NULL }, +}; + +/** @} */ diff --git a/apps/shell/shell-commands.h b/apps/shell/shell-commands.h new file mode 100644 index 000000000..fbff6e675 --- /dev/null +++ b/apps/shell/shell-commands.h @@ -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 + */ + +/** \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, const 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_ */ + +/** @} */ diff --git a/apps/shell/shell.c b/apps/shell/shell.c new file mode 100644 index 000000000..d6ef20ccb --- /dev/null +++ b/apps/shell/shell.c @@ -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 + */ + +/** + * \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(); +} +/** @} */ diff --git a/apps/shell/shell.h b/apps/shell/shell.h new file mode 100644 index 000000000..2b4763750 --- /dev/null +++ b/apps/shell/shell.h @@ -0,0 +1,88 @@ +/* + * 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 + */ + +/** \addtogroup apps + * @{ */ + +#ifndef SHELL_H_ +#define SHELL_H_ + +#include "net/ip/uip.h" +#include "net/linkaddr.h" +#include "sys/process.h" +#include + +/* 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_ */ + +/** @} */ From 0d6282171f0913277312a95f4e1db1471435cde6 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Thu, 6 Jul 2017 19:31:14 +0200 Subject: [PATCH 04/21] Enable Shell in rpl-tsch example --- examples/ipv6/rpl-tsch/Makefile | 2 +- examples/ipv6/rpl-tsch/node.c | 9 ++++++++- examples/ipv6/rpl-tsch/project-conf.h | 10 +++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/ipv6/rpl-tsch/Makefile b/examples/ipv6/rpl-tsch/Makefile index 734c1499e..3abe2ab7d 100644 --- a/examples/ipv6/rpl-tsch/Makefile +++ b/examples/ipv6/rpl-tsch/Makefile @@ -8,7 +8,7 @@ CONTIKI_WITH_IPV6 = 1 MAKE_WITH_ORCHESTRA ?= 0 # force Orchestra from command line MAKE_WITH_SECURITY ?= 0 # force Security from command line -APPS += orchestra +APPS += orchestra shell MODULES += core/net/mac/tsch ifeq ($(MAKE_WITH_ORCHESTRA),1) diff --git a/examples/ipv6/rpl-tsch/node.c b/examples/ipv6/rpl-tsch/node.c index b1ad2e567..6980c9963 100644 --- a/examples/ipv6/rpl-tsch/node.c +++ b/examples/ipv6/rpl-tsch/node.c @@ -48,6 +48,9 @@ #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" @@ -131,7 +134,7 @@ print_network_status(void) PRINT6ADDR(&child_ipaddr); if(link->parent == NULL) { memset(&parent_ipaddr, 0, sizeof(parent_ipaddr)); - PRINTF(" --- DODAG root "); + PRINTF(" to DODAG root "); } else { PRINTF(" to "); PRINT6ADDR(&parent_ipaddr); @@ -174,6 +177,10 @@ PROCESS_THREAD(node_process, ev, data) int coordinator_candidate = 0; +#if WITH_SHELL + serial_shell_init(); +#endif /* WITH_SHELL */ + #if CONTIKI_TARGET_COOJA coordinator_candidate = (node_id == 1); #endif diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index 16b05fffa..610a4aa20 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -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,11 @@ #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 +#endif /* WITH_SHELL */ + /* Needed for cc2420 platforms only */ /* Disable DCO calibration (uses timerB) */ #undef DCOSYNCH_CONF_ENABLED @@ -89,7 +97,7 @@ /* TSCH per-slot logging */ #undef TSCH_LOG_CONF_PER_SLOT -#define TSCH_LOG_CONF_PER_SLOT 1 +#define TSCH_LOG_CONF_PER_SLOT 0 /* IEEE802.15.4 PANID */ #undef IEEE802154_CONF_PANID From 75f3a154ad05439441d1e41c7a4909f5f275af59 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Thu, 6 Jul 2017 19:43:44 +0200 Subject: [PATCH 05/21] Added shell command to configure log level at runtime --- apps/shell/shell-commands.c | 49 +++++++++++++++++++++++++-- core/net/mac/tsch/tsch-log.c | 22 ++++++++++-- core/net/mac/tsch/tsch-log.h | 2 ++ core/sys/log-conf.h | 7 ++++ core/sys/log.c | 36 +++++++++++++++++++- core/sys/log.h | 39 ++++++++++++++++----- examples/ipv6/rpl-tsch/project-conf.h | 22 +++++++++--- 7 files changed, 159 insertions(+), 18 deletions(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index 611335c5f..3f2b70861 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -45,9 +45,13 @@ #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/mac/tsch/tsch-log.h" + +#include #define PING_TIMEOUT (5 * CLOCK_SECOND) @@ -109,6 +113,46 @@ PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, const char *args)) } /*---------------------------------------------------------------------------*/ static +PT_THREAD(cmd_log(struct pt *pt, shell_output_func output, const char *args)) +{ + static char *next_args; + int prev_level; + int level; + + PT_BEGIN(pt); + + /* Isolate first argument */ + next_args = strchr(args, ' '); + if(next_args != NULL) { + *next_args = '\0'; + next_args++; + } + + /* Parse argument */ + level = (int)strtol(args, NULL, 10); + + /* Set log level */ + if(level >= LOG_LEVEL_NONE && level <= LOG_LEVEL_DBG) { + prev_level = log_get_level(); + if(level != prev_level) { + log_set_level(level); + 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(output, "Log level set to %u (%s)\n", level, log_level_to_str(level)); + } else { + SHELL_OUTPUT(output, "Invalid argument: %s\n", args); + } + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static PT_THREAD(cmd_help(struct pt *pt, shell_output_func output, const char *args)) { PT_BEGIN(pt); @@ -133,8 +177,9 @@ shell_commands_init(void) } /*---------------------------------------------------------------------------*/ struct shell_command_t shell_commands[] = { - { "help", cmd_help, "'> help': Shows this help" }, - { "ping", cmd_ping, "'> ping addr': Pings the IPv6 address 'addr'" }, + { "help", cmd_help, "'> help': Shows this help" }, + { "ping", cmd_ping, "'> ping addr': Pings the IPv6 address 'addr'" }, + { "log", cmd_log, "'> log level': Sets log level (0--4). Level 4 also enables TSCH per-slot logging." }, { NULL, NULL, NULL }, }; diff --git a/core/net/mac/tsch/tsch-log.c b/core/net/mac/tsch/tsch-log.c index f4089add7..6e2e1aa49 100644 --- a/core/net/mac/tsch/tsch-log.c +++ b/core/net/mac/tsch/tsch-log.c @@ -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 */ @@ -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 */ diff --git a/core/net/mac/tsch/tsch-log.h b/core/net/mac/tsch/tsch-log.h index d86a4c137..92c6568c6 100644 --- a/core/net/mac/tsch/tsch-log.h +++ b/core/net/mac/tsch/tsch-log.h @@ -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 **********/ diff --git a/core/sys/log-conf.h b/core/sys/log-conf.h index 6eb526d6f..6c81fd8d6 100644 --- a/core/sys/log-conf.h +++ b/core/sys/log-conf.h @@ -67,6 +67,13 @@ #define LOG_WITH_ANNOTATE 0 #endif /* LOG_CONF_WITH_ANNOTATE */ +/* Log level at startup. Can be modified at runtime via log_set_level() */ +#ifdef LOG_CONF_START_LEVEL +#define LOG_START_LEVEL LOG_CONF_START_LEVEL +#else /* LOG_CONF_START_LEVEL */ +#define LOG_START_LEVEL LOG_LEVEL_DBG /* All (already compiled) logs are enabled */ +#endif /* LOG_CONF_START_LEVEL */ + /* Custom output function -- default is printf */ #ifdef LOG_CONF_OUTPUT #define LOG_OUTPUT(...) LOG_CONF_OUTPUT(__VA_ARGS__) diff --git a/core/sys/log.c b/core/sys/log.c index abfb16d15..adfa6027f 100644 --- a/core/sys/log.c +++ b/core/sys/log.c @@ -53,6 +53,8 @@ #include "sys/log.h" #include "net/ip/ip64-addr.h" +int curr_log_level = LOG_START_LEVEL; + /*---------------------------------------------------------------------------*/ void log_6addr(const uip_ipaddr_t *ipaddr) @@ -131,6 +133,38 @@ log_lladdr_compact(const linkaddr_t *lladdr) LOG_OUTPUT("LL-%04x", UIP_HTONS(lladdr->u16[LINKADDR_SIZE/2-1])); } } - +/*---------------------------------------------------------------------------*/ +void +log_set_level(int level) +{ + if(level >= LOG_LEVEL_NONE && level <= LOG_LEVEL_DBG) { + curr_log_level = level; + } +} +/*---------------------------------------------------------------------------*/ +int +log_get_level(void) +{ + return curr_log_level; +} +/*---------------------------------------------------------------------------*/ +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"; + } +} /** @} */ /** @} */ diff --git a/core/sys/log.h b/core/sys/log.h index 567cb2cdb..48f0ba77b 100644 --- a/core/sys/log.h +++ b/core/sys/log.h @@ -68,7 +68,7 @@ /* Main log function */ #define LOG(newline, level, levelstr, ...) do { \ - if(level <= LOG_LEVEL) { \ + if(level <= MIN(LOG_LEVEL, curr_log_level)) { \ if(newline) { \ LOG_OUTPUT("[%-4s: %-10s] ", levelstr, LOG_MODULE); \ if(LOG_WITH_LOC) { \ @@ -88,7 +88,7 @@ /* Link-layer address */ #define LOG_LLADDR(level, lladdr) do { \ - if(level <= LOG_LEVEL) { \ + if(level <= MIN(LOG_LEVEL, curr_log_level)) { \ if(LOG_WITH_COMPACT_ADDR) { \ log_lladdr_compact(lladdr); \ } else { \ @@ -99,7 +99,7 @@ /* IPv6 address */ #define LOG_6ADDR(level, ipaddr) do { \ - if(level <= LOG_LEVEL) { \ + if(level <= MIN(LOG_LEVEL, curr_log_level)) { \ if(LOG_WITH_COMPACT_ADDR) { \ log_6addr_compact(ipaddr); \ } else { \ @@ -130,11 +130,13 @@ #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) + +/* The current log level */ +extern int curr_log_level; #if NETSTACK_CONF_WITH_IPV6 @@ -164,6 +166,27 @@ 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 level The log level +*/ +void log_set_level(int level); + +/** + * Returns the current log level. + * \return The current log level +*/ +int log_get_level(void); + +/** + * 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__ */ /** @} */ diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index 610a4aa20..14e604212 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -81,6 +81,13 @@ #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 */ @@ -95,10 +102,6 @@ /******************* Configure TSCH ********************/ /*******************************************************/ -/* TSCH per-slot logging */ -#undef TSCH_LOG_CONF_PER_SLOT -#define TSCH_LOG_CONF_PER_SLOT 0 - /* IEEE802.15.4 PANID */ #undef IEEE802154_CONF_PANID #define IEEE802154_CONF_PANID 0xabcd @@ -153,4 +156,15 @@ #define TSCH_CONF_MAX_EB_PERIOD (4 * CLOCK_SECOND) #endif /* CONTIKI_TARGET_COOJA */ +/* Logging */ +#define RPL_LOG_LEVEL LOG_LEVEL_INFO +#define TCPIP_LOG_LEVEL LOG_LEVEL_WARN +#define IPV6_LOG_LEVEL LOG_LEVEL_WARN +#define SICSLOWPAN_LOG_LEVEL LOG_LEVEL_WARN +#define MAC_LOG_LEVEL LOG_LEVEL_INFO +#define FRAMER_LOG_LEVEL LOG_LEVEL_WARN +#define TSCH_LOG_CONF_PER_SLOT 1 + +#define LOG_CONF_START_LEVEL LOG_LEVEL_WARN + #endif /* __PROJECT_CONF_H__ */ From 9ddae0c90f1bec435242d2e197a62b4c96ecbd57 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 7 Jul 2017 09:56:37 +0200 Subject: [PATCH 06/21] Update serialdump-linux binaries --- tools/jn516x/serialdump-linux | Bin 0 -> 12663 bytes tools/sky/serialdump-linux | Bin 14922 -> 12728 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/jn516x/serialdump-linux diff --git a/tools/jn516x/serialdump-linux b/tools/jn516x/serialdump-linux new file mode 100644 index 0000000000000000000000000000000000000000..69fd8cfdbb5347bfc6e91999ffc9685af6722e94 GIT binary patch literal 12663 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 literal 14922 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 From 07b53738299975517177ffacdc9e96efd3baafcc Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 7 Jul 2017 15:11:51 +0200 Subject: [PATCH 07/21] Shell: easier argument parsing --- apps/shell/shell-commands.c | 56 ++++++++++++++++++++++++++++++------- apps/shell/shell-commands.h | 2 +- apps/shell/shell.h | 20 +++++++++++++ 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index 3f2b70861..2f430b81a 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -73,21 +73,18 @@ echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t da } /*---------------------------------------------------------------------------*/ static -PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, const char *args)) +PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, char *args)) { static uip_ipaddr_t remote_addr; - static char *next_args; static struct etimer timeout_timer; + char *next_args; PT_BEGIN(pt); - /* Isolate first argument */ - next_args = strchr(args, ' '); - if(next_args != NULL) { - *next_args = '\0'; - next_args++; - } + 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); @@ -153,13 +150,52 @@ PT_THREAD(cmd_log(struct pt *pt, shell_output_func output, const char *args)) } /*---------------------------------------------------------------------------*/ static -PT_THREAD(cmd_help(struct pt *pt, shell_output_func output, const char *args)) +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; + PT_BEGIN(pt); - struct shell_command_t *cmd_ptr = shell_commands; + SHELL_ARGS_INIT(args, next_args); + + /* Get and parse argument */ + SHELL_ARGS_NEXT(args, next_args); + level = (int)strtol(args, &ptr, 10); + if((level == 0 && args == ptr) + || level < LOG_LEVEL_NONE || level > LOG_LEVEL_DBG) { + SHELL_OUTPUT(output, "Invalid argument: %s\n", args); + PT_EXIT(pt); + } + + /* Set log level */ + prev_level = log_get_level(); + if(level != prev_level) { + log_set_level(level); + 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(output, "Log level set to %u (%s)\n", level, log_level_to_str(level)); + + 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++; diff --git a/apps/shell/shell-commands.h b/apps/shell/shell-commands.h index fbff6e675..4e6aa0f40 100644 --- a/apps/shell/shell-commands.h +++ b/apps/shell/shell-commands.h @@ -44,7 +44,7 @@ #define _SHELL_COMMANDS_H_ /* Command handling function type */ -typedef char (shell_commands_func)(struct pt *pt, shell_output_func output, const char *args); +typedef char (shell_commands_func)(struct pt *pt, shell_output_func output, char *args); /* Command structure */ struct shell_command_t { diff --git a/apps/shell/shell.h b/apps/shell/shell.h index 2b4763750..938cb6998 100644 --- a/apps/shell/shell.h +++ b/apps/shell/shell.h @@ -48,6 +48,26 @@ #include "sys/process.h" #include +/* 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]; \ From b81375f6380191fcec5b657dbc1f150a45a7efac Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 7 Jul 2017 15:12:23 +0200 Subject: [PATCH 08/21] Shell: added command to set node as root (or unsed) --- apps/shell/shell-commands.c | 82 ++++++++++++++++++++++++------------- core/net/rpl-lite/rpl-dag.c | 3 +- core/net/rpl-lite/rpl-ns.c | 17 +++++++- core/net/rpl-lite/rpl-ns.h | 5 +++ 4 files changed, 76 insertions(+), 31 deletions(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index 2f430b81a..2282beff1 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -49,7 +49,14 @@ #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-log.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 @@ -110,40 +117,56 @@ PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, char *args)) } /*---------------------------------------------------------------------------*/ static -PT_THREAD(cmd_log(struct pt *pt, shell_output_func output, const char *args)) +PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) { - static char *next_args; - int prev_level; - int level; + static int is_on; + static uip_ipaddr_t prefix; + char *next_args; PT_BEGIN(pt); - /* Isolate first argument */ - next_args = strchr(args, ' '); - if(next_args != NULL) { - *next_args = '\0'; - next_args++; - } + SHELL_ARGS_INIT(args, next_args); - /* Parse argument */ - level = (int)strtol(args, NULL, 10); + /* Get first arg (0/1) */ + SHELL_ARGS_NEXT(args, next_args); - /* Set log level */ - if(level >= LOG_LEVEL_NONE && level <= LOG_LEVEL_DBG) { - prev_level = log_get_level(); - if(level != prev_level) { - log_set_level(level); - 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(output, "Log level set to %u (%s)\n", level, log_level_to_str(level)); + 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_leave(); + } else { + SHELL_OUTPUT(output, "Node is not a DAG root\n"); + } } PT_END(pt); @@ -213,9 +236,10 @@ shell_commands_init(void) } /*---------------------------------------------------------------------------*/ struct shell_command_t shell_commands[] = { - { "help", cmd_help, "'> help': Shows this help" }, - { "ping", cmd_ping, "'> ping addr': Pings the IPv6 address 'addr'" }, - { "log", cmd_log, "'> log level': Sets log level (0--4). Level 4 also enables TSCH per-slot logging." }, + { "help", cmd_help, "'> help': Shows this help" }, + { "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." }, + { "log", cmd_log, "'> log level': Sets log level (0--4). Level 4 also enables TSCH per-slot logging." }, { NULL, NULL, NULL }, }; diff --git a/core/net/rpl-lite/rpl-dag.c b/core/net/rpl-lite/rpl-dag.c index 4b39f40d8..9fcc9f3bc 100644 --- a/core/net/rpl-lite/rpl-dag.c +++ b/core/net/rpl-lite/rpl-dag.c @@ -94,8 +94,9 @@ rpl_dag_leave(void) /* 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(); diff --git a/core/net/rpl-lite/rpl-ns.c b/core/net/rpl-lite/rpl-ns.c index 650f4fb98..672e0478f 100644 --- a/core/net/rpl-lite/rpl-ns.c +++ b/core/net/rpl-lite/rpl-ns.c @@ -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--; + } +} diff --git a/core/net/rpl-lite/rpl-ns.h b/core/net/rpl-lite/rpl-ns.h index c09d0f6ad..8077cdf57 100644 --- a/core/net/rpl-lite/rpl-ns.h +++ b/core/net/rpl-lite/rpl-ns.h @@ -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 */ From 09e0d75b53f5b27462ead50e4cf768ea9200a03d Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 7 Jul 2017 15:23:32 +0200 Subject: [PATCH 09/21] Simplify rpl-tsch example --- examples/ipv6/rpl-tsch/node.c | 87 +++-------------------------------- 1 file changed, 6 insertions(+), 81 deletions(-) diff --git a/examples/ipv6/rpl-tsch/node.c b/examples/ipv6/rpl-tsch/node.c index 6980c9963..105555ff4 100644 --- a/examples/ipv6/rpl-tsch/node.c +++ b/examples/ipv6/rpl-tsch/node.c @@ -55,18 +55,9 @@ #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 @@ -147,93 +138,27 @@ print_network_status(void) 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; - - int coordinator_candidate = 0; + is_coordinator = 0; #if WITH_SHELL serial_shell_init(); #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(); From 03f76a9058faf13d1b210691d95eefc60193230f Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 7 Jul 2017 15:43:31 +0200 Subject: [PATCH 10/21] Shell ping command: print out delay --- apps/shell/shell-commands.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index 2282beff1..bf88c63e2 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -65,16 +65,17 @@ 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 void echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen) { if(curr_ping_output_func != NULL) { - SHELL_OUTPUT(curr_ping_output_func, "Received ping reply from "); - shell_output_6addr(curr_ping_output_func, source); - SHELL_OUTPUT(curr_ping_output_func, ", ttl %u, len %u\n", ttl, datalen); curr_ping_output_func = NULL; + curr_ping_ttl = ttl; + curr_ping_datalen = datalen; process_poll(curr_ping_process); } } @@ -111,6 +112,11 @@ PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, char *args)) 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 %u ms\n", + curr_ping_datalen, curr_ping_ttl, (1000*(unsigned)(clock_time() - timeout_timer.timer.start))/CLOCK_SECOND); } PT_END(pt); From 5999323a050c0adb7e349f80b02ab9aac5a86ec4 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 7 Jul 2017 18:05:27 +0200 Subject: [PATCH 11/21] More Shell commands --- apps/shell/shell-commands.c | 112 +++++++++++++++++- core/net/mac/tsch/tsch-log.c | 6 +- core/net/mac/tsch/tsch.h | 2 +- core/net/rpl-lite/rpl-dag.c | 5 +- core/sys/log-conf.h | 7 -- core/sys/log.c | 2 +- examples/ipv6/rpl-tsch/Makefile | 5 + examples/ipv6/rpl-tsch/node.c | 106 ++++------------- examples/ipv6/rpl-tsch/project-conf.h | 4 +- .../08-ipv6/19-cooja-rpl-tsch.csc | 4 +- .../08-ipv6/20-cooja-rpl-tsch-orchestra.csc | 4 +- .../08-ipv6/21-cooja-rpl-tsch-security.csc | 4 +- 12 files changed, 151 insertions(+), 110 deletions(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index bf88c63e2..bfbd94e32 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -115,8 +115,8 @@ PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, char *args)) } else { SHELL_OUTPUT(output, "Received ping reply from "); shell_output_6addr(output, &remote_addr); - SHELL_OUTPUT(output, ", len %u, ttl %u, delay %u ms\n", - curr_ping_datalen, curr_ping_ttl, (1000*(unsigned)(clock_time() - timeout_timer.timer.start))/CLOCK_SECOND); + 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); @@ -233,6 +233,112 @@ PT_THREAD(cmd_help(struct pt *pt, shell_output_func output, char *args)) PT_END(pt); } /*---------------------------------------------------------------------------*/ +static +PT_THREAD(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(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); +} +/*---------------------------------------------------------------------------*/ void shell_commands_init(void) { @@ -243,8 +349,10 @@ shell_commands_init(void) /*---------------------------------------------------------------------------*/ struct shell_command_t shell_commands[] = { { "help", cmd_help, "'> help': Shows this help" }, + { "ipaddr", ipaddr, "'> ipaddr': Shows all IPv6 addresses" }, { "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." }, + { "routes", routes, "'> routes': Shows the route entries" }, { "log", cmd_log, "'> log level': Sets log level (0--4). Level 4 also enables TSCH per-slot logging." }, { NULL, NULL, NULL }, }; diff --git a/core/net/mac/tsch/tsch-log.c b/core/net/mac/tsch/tsch-log.c index 6e2e1aa49..e92311217 100644 --- a/core/net/mac/tsch/tsch-log.c +++ b/core/net/mac/tsch/tsch-log.c @@ -74,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)); diff --git a/core/net/mac/tsch/tsch.h b/core/net/mac/tsch/tsch.h index b56ffaf3a..d436b69af 100644 --- a/core/net/mac/tsch/tsch.h +++ b/core/net/mac/tsch/tsch.h @@ -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 */ diff --git a/core/net/rpl-lite/rpl-dag.c b/core/net/rpl-lite/rpl-dag.c index 9fcc9f3bc..9d9ee06ea 100644 --- a/core/net/rpl-lite/rpl-dag.c +++ b/core/net/rpl-lite/rpl-dag.c @@ -517,8 +517,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); @@ -526,6 +524,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; } /*---------------------------------------------------------------------------*/ diff --git a/core/sys/log-conf.h b/core/sys/log-conf.h index 6c81fd8d6..6eb526d6f 100644 --- a/core/sys/log-conf.h +++ b/core/sys/log-conf.h @@ -67,13 +67,6 @@ #define LOG_WITH_ANNOTATE 0 #endif /* LOG_CONF_WITH_ANNOTATE */ -/* Log level at startup. Can be modified at runtime via log_set_level() */ -#ifdef LOG_CONF_START_LEVEL -#define LOG_START_LEVEL LOG_CONF_START_LEVEL -#else /* LOG_CONF_START_LEVEL */ -#define LOG_START_LEVEL LOG_LEVEL_DBG /* All (already compiled) logs are enabled */ -#endif /* LOG_CONF_START_LEVEL */ - /* Custom output function -- default is printf */ #ifdef LOG_CONF_OUTPUT #define LOG_OUTPUT(...) LOG_CONF_OUTPUT(__VA_ARGS__) diff --git a/core/sys/log.c b/core/sys/log.c index adfa6027f..a112943c0 100644 --- a/core/sys/log.c +++ b/core/sys/log.c @@ -53,7 +53,7 @@ #include "sys/log.h" #include "net/ip/ip64-addr.h" -int curr_log_level = LOG_START_LEVEL; +int curr_log_level = LOG_LEVEL_DBG; /*---------------------------------------------------------------------------*/ void diff --git a/examples/ipv6/rpl-tsch/Makefile b/examples/ipv6/rpl-tsch/Makefile index 3abe2ab7d..03173e2a1 100644 --- a/examples/ipv6/rpl-tsch/Makefile +++ b/examples/ipv6/rpl-tsch/Makefile @@ -7,6 +7,7 @@ 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 shell MODULES += core/net/mac/tsch @@ -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 diff --git a/examples/ipv6/rpl-tsch/node.c b/examples/ipv6/rpl-tsch/node.c index 105555ff4..dfc386b41 100644 --- a/examples/ipv6/rpl-tsch/node.c +++ b/examples/ipv6/rpl-tsch/node.c @@ -40,8 +40,10 @@ #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 */ @@ -59,88 +61,9 @@ PROCESS(node_process, "RPL Node"); AUTOSTART_PROCESSES(&node_process); -/*---------------------------------------------------------------------------*/ -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(" to 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"); -} /*---------------------------------------------------------------------------*/ PROCESS_THREAD(node_process, ev, data) { - static struct etimer et; int is_coordinator; PROCESS_BEGIN(); @@ -149,6 +72,8 @@ PROCESS_THREAD(node_process, ev, data) #if WITH_SHELL serial_shell_init(); + log_set_level(LOG_LEVEL_WARN); + tsch_log_stop(); #endif /* WITH_SHELL */ #if CONTIKI_TARGET_COOJA @@ -164,13 +89,24 @@ PROCESS_THREAD(node_process, ev, data) 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(); } diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index 14e604212..fa5cf2425 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -104,7 +104,7 @@ /* 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 @@ -165,6 +165,4 @@ #define FRAMER_LOG_LEVEL LOG_LEVEL_WARN #define TSCH_LOG_CONF_PER_SLOT 1 -#define LOG_CONF_START_LEVEL LOG_LEVEL_WARN - #endif /* __PROJECT_CONF_H__ */ diff --git a/regression-tests/08-ipv6/19-cooja-rpl-tsch.csc b/regression-tests/08-ipv6/19-cooja-rpl-tsch.csc index 112172828..97f4dd798 100644 --- a/regression-tests/08-ipv6/19-cooja-rpl-tsch.csc +++ b/regression-tests/08-ipv6/19-cooja-rpl-tsch.csc @@ -26,7 +26,7 @@ Cooja Mote Type #mtype1 [CONTIKI_DIR]/examples/ipv6/rpl-tsch/node.c make TARGET=cooja clean -make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=0 +make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1 org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.Battery org.contikios.cooja.contikimote.interfaces.ContikiVib @@ -278,7 +278,7 @@ log.log("Waiting for routing links to fill\n"); while(true) {; WAIT_UNTIL(id == 1 && msg.contains("Routing links")); log.log(msg + "\n"); - if(msg.contains("Routing links (9 in total):")) { + if(msg.contains("Routing links: 9")) { log.testOK(); /* Report test success and quit */ } YIELD(); diff --git a/regression-tests/08-ipv6/20-cooja-rpl-tsch-orchestra.csc b/regression-tests/08-ipv6/20-cooja-rpl-tsch-orchestra.csc index 192617b23..676d86366 100644 --- a/regression-tests/08-ipv6/20-cooja-rpl-tsch-orchestra.csc +++ b/regression-tests/08-ipv6/20-cooja-rpl-tsch-orchestra.csc @@ -26,7 +26,7 @@ Cooja Mote Type #mtype11 [CONTIKI_DIR]/examples/ipv6/rpl-tsch/node.c make TARGET=cooja clean -make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=1 MAKE_WITH_SECURITY=0 +make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=1 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1 [CONTIKI_DIR]/examples/ipv6/rpl-tsch/node.mtype1 org.contikios.cooja.interfaces.Position @@ -280,7 +280,7 @@ log.log("Waiting for routing links to fill\n"); while(true) {; WAIT_UNTIL(id == 1 && msg.contains("Routing links")); log.log(msg + "\n"); - if(msg.contains("Routing links (9 in total):")) { + if(msg.contains("Routing links: 9")) { log.testOK(); /* Report test success and quit */ } YIELD(); diff --git a/regression-tests/08-ipv6/21-cooja-rpl-tsch-security.csc b/regression-tests/08-ipv6/21-cooja-rpl-tsch-security.csc index e3e192297..ffa370b01 100644 --- a/regression-tests/08-ipv6/21-cooja-rpl-tsch-security.csc +++ b/regression-tests/08-ipv6/21-cooja-rpl-tsch-security.csc @@ -26,7 +26,7 @@ Cooja Mote Type #mtype11 [CONTIKI_DIR]/examples/ipv6/rpl-tsch/node.c make TARGET=cooja clean -make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=1 +make node.cooja TARGET=cooja MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=1 MAKE_WITH_PERIODIC_ROUTES_PRINT=1 org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.Battery org.contikios.cooja.contikimote.interfaces.ContikiVib @@ -278,7 +278,7 @@ log.log("Waiting for routing links to fill\n"); while(true) {; WAIT_UNTIL(id == 1 && msg.contains("Routing links")); log.log(msg + "\n"); - if(msg.contains("Routing links (9 in total):")) { + if(msg.contains("Routing links: 9")) { log.testOK(); /* Report test success and quit */ } YIELD(); From f7d4d5a0ecd5e64db72057e15048509ddeff4994 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Mon, 10 Jul 2017 16:32:41 +0200 Subject: [PATCH 12/21] Fix Shell log command argument parsing --- apps/shell/shell-commands.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index bfbd94e32..33ce46163 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -192,7 +192,11 @@ PT_THREAD(cmd_log(struct pt *pt, shell_output_func output, char *args)) /* Get and parse argument */ SHELL_ARGS_NEXT(args, next_args); - level = (int)strtol(args, &ptr, 10); + 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 argument: %s\n", args); From 0ea63514e3bb2d8afecbac838cb92e7c7724576a Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Mon, 10 Jul 2017 17:45:07 +0200 Subject: [PATCH 13/21] Shell: added a number of RPL and TSCH mngt functions --- apps/shell/shell-commands.c | 166 ++++++++++++++++++++- core/net/mac/tsch/tsch-adaptive-timesync.c | 8 +- core/net/mac/tsch/tsch-adaptive-timesync.h | 2 + core/net/mac/tsch/tsch-slot-operation.c | 4 + core/net/mac/tsch/tsch-slot-operation.h | 2 + core/net/rpl-lite/rpl-dag.c | 4 +- 6 files changed, 176 insertions(+), 10 deletions(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index 33ce46163..c1cf3d9ee 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -50,7 +50,11 @@ #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 */ @@ -68,6 +72,53 @@ static struct process *curr_ping_process; static uint8_t curr_ping_ttl; static uint16_t curr_ping_datalen; +/*---------------------------------------------------------------------------*/ +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) @@ -238,7 +289,29 @@ PT_THREAD(cmd_help(struct pt *pt, shell_output_func output, char *args)) } /*---------------------------------------------------------------------------*/ static -PT_THREAD(ipaddr(struct pt *pt, shell_output_func output, char *args)) +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; @@ -257,10 +330,83 @@ PT_THREAD(ipaddr(struct pt *pt, shell_output_func output, char *args)) } PT_END(pt); + } /*---------------------------------------------------------------------------*/ static -PT_THREAD(routes(struct pt *pt, shell_output_func output, char *args)) +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 @@ -352,12 +498,16 @@ shell_commands_init(void) } /*---------------------------------------------------------------------------*/ struct shell_command_t shell_commands[] = { - { "help", cmd_help, "'> help': Shows this help" }, - { "ipaddr", ipaddr, "'> ipaddr': Shows all IPv6 addresses" }, - { "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." }, - { "routes", routes, "'> routes': Shows the route entries" }, - { "log", cmd_log, "'> log level': Sets log level (0--4). Level 4 also enables TSCH per-slot logging." }, + { "help", cmd_help, "'> help': Shows this help" }, + { "ipaddr", cmd_ipaddr, "'> ipaddr': Shows all IPv6 addresses" }, + { "log", cmd_log, "'> log level': Sets log level (0--4). Level 4 also enables TSCH 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-status", cmd_tsch_status, "'> tsch-status': Shows a summary of the current TSCH state" }, { NULL, NULL, NULL }, }; diff --git a/core/net/mac/tsch/tsch-adaptive-timesync.c b/core/net/mac/tsch/tsch-adaptive-timesync.c index 9c23e8f19..430db841d 100644 --- a/core/net/mac/tsch/tsch-adaptive-timesync.c +++ b/core/net/mac/tsch/tsch-adaptive-timesync.c @@ -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 */ diff --git a/core/net/mac/tsch/tsch-adaptive-timesync.h b/core/net/mac/tsch/tsch-adaptive-timesync.h index d043ca021..f928856a7 100644 --- a/core/net/mac/tsch/tsch-adaptive-timesync.h +++ b/core/net/mac/tsch/tsch-adaptive-timesync.h @@ -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__ */ diff --git a/core/net/mac/tsch/tsch-slot-operation.c b/core/net/mac/tsch/tsch-slot-operation.c index 4b2b9faf2..d84a1998d 100644 --- a/core/net/mac/tsch/tsch-slot-operation.c +++ b/core/net/mac/tsch/tsch-slot-operation.c @@ -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; } /*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/tsch/tsch-slot-operation.h b/core/net/mac/tsch/tsch-slot-operation.h index c6af61ce2..74e054b55 100644 --- a/core/net/mac/tsch/tsch-slot-operation.h +++ b/core/net/mac/tsch/tsch-slot-operation.h @@ -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 *********/ diff --git a/core/net/rpl-lite/rpl-dag.c b/core/net/rpl-lite/rpl-dag.c index 9d9ee06ea..4ac21ed2e 100644 --- a/core/net/rpl-lite/rpl-dag.c +++ b/core/net/rpl-lite/rpl-dag.c @@ -198,8 +198,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 */ From 385d709f3cb296e7822ff68d2b711b141ea52bed Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Mon, 10 Jul 2017 17:45:31 +0200 Subject: [PATCH 14/21] cc2538 TSCH: set base drift to compensate for inaccuracy of running a 32k timer --- arch/platform/cc2538dk/contiki-conf.h | 5 +++++ arch/platform/openmote-cc2538/contiki-conf.h | 5 +++++ arch/platform/zoul/contiki-conf.h | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/arch/platform/cc2538dk/contiki-conf.h b/arch/platform/cc2538dk/contiki-conf.h index 23e9dc60d..307b015fe 100644 --- a/arch/platform/cc2538dk/contiki-conf.h +++ b/arch/platform/cc2538dk/contiki-conf.h @@ -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 diff --git a/arch/platform/openmote-cc2538/contiki-conf.h b/arch/platform/openmote-cc2538/contiki-conf.h index 83c975b7e..d28a85ba3 100644 --- a/arch/platform/openmote-cc2538/contiki-conf.h +++ b/arch/platform/openmote-cc2538/contiki-conf.h @@ -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 diff --git a/arch/platform/zoul/contiki-conf.h b/arch/platform/zoul/contiki-conf.h index 59ab8a665..38b34e5ad 100644 --- a/arch/platform/zoul/contiki-conf.h +++ b/arch/platform/zoul/contiki-conf.h @@ -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 From 38ce63a61452abcbc359495b897d2f32e0ec7c28 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Tue, 11 Jul 2017 15:44:48 +0200 Subject: [PATCH 15/21] jn516x: minor fixes --- arch/platform/jn516x/lib/sprintf.c | 8 +++++--- core/net/rpl-lite/rpl-ext-header.c | 10 +++++----- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/arch/platform/jn516x/lib/sprintf.c b/arch/platform/jn516x/lib/sprintf.c index 500951e92..ed93f9885 100644 --- a/arch/platform/jn516x/lib/sprintf.c +++ b/arch/platform/jn516x/lib/sprintf.c @@ -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++; } } diff --git a/core/net/rpl-lite/rpl-ext-header.c b/core/net/rpl-lite/rpl-ext-header.c index d16de80b3..55c66f5ab 100644 --- a/core/net/rpl-lite/rpl-ext-header.c +++ b/core/net/rpl-lite/rpl-ext-header.c @@ -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 */ } From c6537820b1c37fdcf90399d39008757775154a58 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 14 Jul 2017 14:29:17 +0200 Subject: [PATCH 16/21] Minor rpl-lite fixes for DAG leaving/joining --- apps/shell/shell-commands.c | 2 +- core/net/rpl-lite/rpl-dag.c | 180 ++++++++++++++++++---------------- core/net/rpl-lite/rpl-dag.h | 5 + core/net/rpl-lite/rpl-icmp6.c | 17 +++- 4 files changed, 114 insertions(+), 90 deletions(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index c1cf3d9ee..9e8c27eb7 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -220,7 +220,7 @@ PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) } else { if(rpl_dag_root_is_root()) { SHELL_OUTPUT(output, "Setting as non-root node: leaving DAG\n"); - rpl_dag_leave(); + rpl_dag_poison_and_leave(); } else { SHELL_OUTPUT(output, "Node is not a DAG root\n"); } diff --git a/core/net/rpl-lite/rpl-dag.c b/core/net/rpl-lite/rpl-dag.c index 4ac21ed2e..7c4c3f299 100644 --- a/core/net/rpl-lite/rpl-dag.c +++ b/core/net/rpl-lite/rpl-dag.c @@ -88,8 +88,10 @@ 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(); @@ -111,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) { @@ -223,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 * diff --git a/core/net/rpl-lite/rpl-dag.h b/core/net/rpl-lite/rpl-dag.h index e7cd0332f..07ef3ca66 100644 --- a/core/net/rpl-lite/rpl-dag.h +++ b/core/net/rpl-lite/rpl-dag.h @@ -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 * diff --git a/core/net/rpl-lite/rpl-icmp6.c b/core/net/rpl-lite/rpl-icmp6.c index 1e54c2237..756689bbd 100644 --- a/core/net/rpl-lite/rpl-icmp6.c +++ b/core/net/rpl-lite/rpl-icmp6.c @@ -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; } From a223022a747f20e47d12d6211cdb83deaa4a1e4a Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 14 Jul 2017 14:29:38 +0200 Subject: [PATCH 17/21] rpl-lite: fix delayed DAG leaving --- core/net/rpl-lite/rpl-timers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/rpl-lite/rpl-timers.c b/core/net/rpl-lite/rpl-timers.c index 36a5b6267..fc236be14 100644 --- a/core/net/rpl-lite/rpl-timers.c +++ b/core/net/rpl-lite/rpl-timers.c @@ -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); } } } From 2fdc1d9134f5dacfbcf0d181065d0666121f4c24 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Fri, 14 Jul 2017 14:41:42 +0200 Subject: [PATCH 18/21] 6LoWPAN: discard empty packet --- core/net/ipv6/sicslowpan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index 95064e8ea..c5ccf91b1 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -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; From 48c809a32077e6819b6655263a9f2c8b62f02692 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Sat, 15 Jul 2017 09:49:39 +0200 Subject: [PATCH 19/21] Shell: added command to print tsch schedule Conflicts: apps/shell/shell-commands.c --- apps/shell/shell-commands.c | 37 +++++++++++++++++++++++++++++++ core/net/mac/tsch/tsch-schedule.c | 12 ++++++++++ core/net/mac/tsch/tsch-schedule.h | 3 +++ 3 files changed, 52 insertions(+) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index 9e8c27eb7..48edf55e0 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -489,6 +489,42 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args)) 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) { @@ -507,6 +543,7 @@ struct shell_command_t shell_commands[] = { { "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 }, }; diff --git a/core/net/mac/tsch/tsch-schedule.c b/core/net/mac/tsch/tsch-schedule.c index 378a34ff8..3ea8a1b43 100644 --- a/core/net/mac/tsch/tsch-schedule.c +++ b/core/net/mac/tsch/tsch-schedule.c @@ -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) diff --git a/core/net/mac/tsch/tsch-schedule.h b/core/net/mac/tsch/tsch-schedule.h index 75f757e66..1099664a9 100644 --- a/core/net/mac/tsch/tsch-schedule.h +++ b/core/net/mac/tsch/tsch-schedule.h @@ -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__ */ From 2847a05e0ac20eb11c841ef04c538c7a5744e892 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Sat, 15 Jul 2017 12:35:59 +0200 Subject: [PATCH 20/21] Shell: new command to show list of IPv6 nbrs --- apps/shell/shell-commands.c | 51 ++++++++++++++++++++++++++++++++++++- core/net/ipv6/uip-ds6-nbr.c | 12 +++++++++ core/net/ipv6/uip-ds6-nbr.h | 2 ++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index 48edf55e0..3d53f7d94 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -72,6 +72,25 @@ 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) @@ -331,6 +350,35 @@ PT_THREAD(cmd_ipaddr(struct pt *pt, shell_output_func output, char *args)) 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 @@ -535,7 +583,8 @@ shell_commands_init(void) /*---------------------------------------------------------------------------*/ struct shell_command_t shell_commands[] = { { "help", cmd_help, "'> help': Shows this help" }, - { "ipaddr", cmd_ipaddr, "'> ipaddr': Shows all IPv6 addresses" }, + { "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 level': Sets log level (0--4). Level 4 also enables TSCH 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." }, diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index 90ff7e27e..7091e497c 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -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); diff --git a/core/net/ipv6/uip-ds6-nbr.h b/core/net/ipv6/uip-ds6-nbr.h index e4a2fee42..6e199a11f 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -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 /** From 8966460b1f29e6289716a56651799063b8371fdb Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Sat, 15 Jul 2017 15:19:09 +0200 Subject: [PATCH 21/21] Added per-module runtime log level configuration --- apps/shell/shell-commands.c | 54 ++++++++++++++++++++------- core/net/ip/tcpip.c | 2 +- core/net/ipv6/sicslowpan.c | 2 +- core/net/ipv6/uip-ds6-nbr.c | 2 +- core/net/ipv6/uip-ds6-route.c | 2 +- core/net/ipv6/uip-ds6.c | 2 +- core/net/ipv6/uip-icmp6.c | 2 +- core/net/ipv6/uip-nd6.c | 2 +- core/net/ipv6/uip6.c | 2 +- core/net/ipv6/websocket-http-client.c | 2 +- core/net/ipv6/websocket.c | 2 +- core/net/mac/csma/csma-output.c | 2 +- core/net/mac/csma/csma.c | 2 +- core/net/mac/framer/frame802154e-ie.c | 2 +- core/net/mac/framer/framer-802154.c | 2 +- core/net/mac/mac.c | 2 +- core/net/mac/tsch/tsch-log.h | 2 +- core/net/mac/tsch/tsch-packet.c | 2 +- core/net/mac/tsch/tsch-queue.c | 2 +- core/net/mac/tsch/tsch-rpl.c | 2 +- core/net/mac/tsch/tsch-schedule.c | 2 +- core/net/mac/tsch/tsch.c | 2 +- core/net/rpl-lite/rpl-dag-root.c | 2 +- core/net/rpl-lite/rpl-dag.c | 2 +- core/net/rpl-lite/rpl-ext-header.c | 2 +- core/net/rpl-lite/rpl-icmp6.c | 2 +- core/net/rpl-lite/rpl-mrhof.c | 2 +- core/net/rpl-lite/rpl-nbr-policy.c | 2 +- core/net/rpl-lite/rpl-neighbor.c | 2 +- core/net/rpl-lite/rpl-ns.c | 2 +- core/net/rpl-lite/rpl-of0.c | 2 +- core/net/rpl-lite/rpl-timers.c | 2 +- core/net/rpl-lite/rpl.c | 2 +- core/sys/log-conf.h | 36 +++++++++--------- core/sys/log.c | 40 +++++++++++++++++--- core/sys/log.h | 39 +++++++++++++++---- examples/ipv6/rpl-tsch/node.c | 2 +- examples/ipv6/rpl-tsch/project-conf.h | 14 +++---- examples/logging/project-conf.h | 11 +++--- 39 files changed, 170 insertions(+), 90 deletions(-) diff --git a/apps/shell/shell-commands.c b/apps/shell/shell-commands.c index 3d53f7d94..89e4bf79f 100644 --- a/apps/shell/shell-commands.c +++ b/apps/shell/shell-commands.c @@ -248,6 +248,19 @@ PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args)) 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)) { @@ -255,12 +268,23 @@ PT_THREAD(cmd_log(struct pt *pt, shell_output_func output, char *args)) static int level; char *next_args; char *ptr; + char *module; PT_BEGIN(pt); SHELL_ARGS_INIT(args, next_args); - /* Get and parse argument */ + /* 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; @@ -269,23 +293,25 @@ PT_THREAD(cmd_log(struct pt *pt, shell_output_func output, char *args)) } if((level == 0 && args == ptr) || level < LOG_LEVEL_NONE || level > LOG_LEVEL_DBG) { - SHELL_OUTPUT(output, "Invalid argument: %s\n", args); + SHELL_OUTPUT(output, "Invalid second argument: %s\n", args); PT_EXIT(pt); } /* Set log level */ - prev_level = log_get_level(); if(level != prev_level) { - log_set_level(level); - 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"); + 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(output, "Log level set to %u (%s)\n", level, log_level_to_str(level)); + + shell_output_log_levels(output); PT_END(pt); } @@ -583,9 +609,9 @@ shell_commands_init(void) /*---------------------------------------------------------------------------*/ 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 level': Sets log level (0--4). Level 4 also enables TSCH per-slot logging." }, + { "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" }, diff --git a/core/net/ip/tcpip.c b/core/net/ip/tcpip.c index 35600e7c6..79ae9702f 100644 --- a/core/net/ip/tcpip.c +++ b/core/net/ip/tcpip.c @@ -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]) diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index c5ccf91b1..22569aebe 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -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 diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index 7091e497c..790adbeba 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -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) diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index eb2479290..ab727e36f 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -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 diff --git a/core/net/ipv6/uip-ds6.c b/core/net/ipv6/uip-ds6.c index 6e7be7b66..11a67e172 100644 --- a/core/net/ipv6/uip-ds6.c +++ b/core/net/ipv6/uip-ds6.c @@ -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 */ diff --git a/core/net/ipv6/uip-icmp6.c b/core/net/ipv6/uip-icmp6.c index a9ec6be6b..c2dbe0f85 100644 --- a/core/net/ipv6/uip-icmp6.c +++ b/core/net/ipv6/uip-icmp6.c @@ -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]) diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index cba9c320c..a432b934e 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -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 /*------------------------------------------------------------------*/ /** @{ */ diff --git a/core/net/ipv6/uip6.c b/core/net/ipv6/uip6.c index 8398a4f95..0df737f43 100644 --- a/core/net/ipv6/uip6.c +++ b/core/net/ipv6/uip6.c @@ -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 /*---------------------------------------------------------------------------*/ /** diff --git a/core/net/ipv6/websocket-http-client.c b/core/net/ipv6/websocket-http-client.c index b712a42f2..4c407c75e 100644 --- a/core/net/ipv6/websocket-http-client.c +++ b/core/net/ipv6/websocket-http-client.c @@ -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, diff --git a/core/net/ipv6/websocket.c b/core/net/ipv6/websocket.c index 9f1fe7a9d..04c6ba506 100644 --- a/core/net/ipv6/websocket.c +++ b/core/net/ipv6/websocket.c @@ -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"); diff --git a/core/net/mac/csma/csma-output.c b/core/net/mac/csma/csma-output.c index 8f0bab4e2..ff63914d3 100644 --- a/core/net/mac/csma/csma-output.c +++ b/core/net/mac/csma/csma-output.c @@ -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 */ diff --git a/core/net/mac/csma/csma.c b/core/net/mac/csma/csma.c index bdcb50c95..aa7a98a3d 100644 --- a/core/net/mac/csma/csma.c +++ b/core/net/mac/csma/csma.c @@ -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 diff --git a/core/net/mac/framer/frame802154e-ie.c b/core/net/mac/framer/frame802154e-ie.c index 20eb98d8b..3ca529360 100644 --- a/core/net/mac/framer/frame802154e-ie.c +++ b/core/net/mac/framer/frame802154e-ie.c @@ -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 { diff --git a/core/net/mac/framer/framer-802154.c b/core/net/mac/framer/framer-802154.c index dab21bda8..52445c0e7 100644 --- a/core/net/mac/framer/framer-802154.c +++ b/core/net/mac/framer/framer-802154.c @@ -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 diff --git a/core/net/mac/mac.c b/core/net/mac/mac.c index 3a6ffff97..c8f8eb87b 100644 --- a/core/net/mac/mac.c +++ b/core/net/mac/mac.c @@ -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 diff --git a/core/net/mac/tsch/tsch-log.h b/core/net/mac/tsch/tsch-log.h index 92c6568c6..7c4acd7b4 100644 --- a/core/net/mac/tsch/tsch-log.h +++ b/core/net/mac/tsch/tsch-log.h @@ -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 */ diff --git a/core/net/mac/tsch/tsch-packet.c b/core/net/mac/tsch/tsch-packet.c index b1fbd23cc..e39766af9 100644 --- a/core/net/mac/tsch/tsch-packet.c +++ b/core/net/mac/tsch/tsch-packet.c @@ -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 */ diff --git a/core/net/mac/tsch/tsch-queue.c b/core/net/mac/tsch/tsch-queue.c index b101f8407..3e940a823 100644 --- a/core/net/mac/tsch/tsch-queue.c +++ b/core/net/mac/tsch/tsch-queue.c @@ -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 diff --git a/core/net/mac/tsch/tsch-rpl.c b/core/net/mac/tsch/tsch-rpl.c index 5689922fc..a609d614a 100644 --- a/core/net/mac/tsch/tsch-rpl.c +++ b/core/net/mac/tsch/tsch-rpl.c @@ -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 */ diff --git a/core/net/mac/tsch/tsch-schedule.c b/core/net/mac/tsch/tsch-schedule.c index 3ea8a1b43..e22b0b498 100644 --- a/core/net/mac/tsch/tsch-schedule.c +++ b/core/net/mac/tsch/tsch-schedule.c @@ -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); diff --git a/core/net/mac/tsch/tsch.c b/core/net/mac/tsch/tsch.c index 567c88af4..a20971ea8 100644 --- a/core/net/mac/tsch/tsch.c +++ b/core/net/mac/tsch/tsch.c @@ -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 */ diff --git a/core/net/rpl-lite/rpl-dag-root.c b/core/net/rpl-lite/rpl-dag-root.c index afb1b6c67..58af56e28 100644 --- a/core/net/rpl-lite/rpl-dag-root.c +++ b/core/net/rpl-lite/rpl-dag-root.c @@ -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) diff --git a/core/net/rpl-lite/rpl-dag.c b/core/net/rpl-lite/rpl-dag.c index 7c4c3f299..99b721b74 100644 --- a/core/net/rpl-lite/rpl-dag.c +++ b/core/net/rpl-lite/rpl-dag.c @@ -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; diff --git a/core/net/rpl-lite/rpl-ext-header.c b/core/net/rpl-lite/rpl-ext-header.c index 55c66f5ab..512761689 100644 --- a/core/net/rpl-lite/rpl-ext-header.c +++ b/core/net/rpl-lite/rpl-ext-header.c @@ -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]) diff --git a/core/net/rpl-lite/rpl-icmp6.c b/core/net/rpl-lite/rpl-icmp6.c index 756689bbd..a150afced 100644 --- a/core/net/rpl-lite/rpl-icmp6.c +++ b/core/net/rpl-lite/rpl-icmp6.c @@ -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 diff --git a/core/net/rpl-lite/rpl-mrhof.c b/core/net/rpl-lite/rpl-mrhof.c index 3784a94f8..faab5ce51 100644 --- a/core/net/rpl-lite/rpl-mrhof.c +++ b/core/net/rpl-lite/rpl-mrhof.c @@ -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 diff --git a/core/net/rpl-lite/rpl-nbr-policy.c b/core/net/rpl-lite/rpl-nbr-policy.c index db49613b2..b25c92d22 100644 --- a/core/net/rpl-lite/rpl-nbr-policy.c +++ b/core/net/rpl-lite/rpl-nbr-policy.c @@ -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 diff --git a/core/net/rpl-lite/rpl-neighbor.c b/core/net/rpl-lite/rpl-neighbor.c index e748e2928..ad128d163 100644 --- a/core/net/rpl-lite/rpl-neighbor.c +++ b/core/net/rpl-lite/rpl-neighbor.c @@ -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 diff --git a/core/net/rpl-lite/rpl-ns.c b/core/net/rpl-lite/rpl-ns.c index 672e0478f..c6f4dfe5d 100644 --- a/core/net/rpl-lite/rpl-ns.c +++ b/core/net/rpl-lite/rpl-ns.c @@ -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; diff --git a/core/net/rpl-lite/rpl-of0.c b/core/net/rpl-lite/rpl-of0.c index 72c01217c..f35cc53cb 100644 --- a/core/net/rpl-lite/rpl-of0.c +++ b/core/net/rpl-lite/rpl-of0.c @@ -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] */ diff --git a/core/net/rpl-lite/rpl-timers.c b/core/net/rpl-lite/rpl-timers.c index fc236be14..b8794e26d 100644 --- a/core/net/rpl-lite/rpl-timers.c +++ b/core/net/rpl-lite/rpl-timers.c @@ -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 diff --git a/core/net/rpl-lite/rpl.c b/core/net/rpl-lite/rpl.c index 003f6dcca..aefa8bc0c 100644 --- a/core/net/rpl-lite/rpl.c +++ b/core/net/rpl-lite/rpl.c @@ -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; diff --git a/core/sys/log-conf.h b/core/sys/log-conf.h index 6eb526d6f..131bf0861 100644 --- a/core/sys/log-conf.h +++ b/core/sys/log-conf.h @@ -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__ */ diff --git a/core/sys/log.c b/core/sys/log.c index a112943c0..8f798ef74 100644 --- a/core/sys/log.c +++ b/core/sys/log.c @@ -53,7 +53,23 @@ #include "sys/log.h" #include "net/ip/ip64-addr.h" -int curr_log_level = LOG_LEVEL_DBG; + +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 @@ -135,17 +151,31 @@ log_lladdr_compact(const linkaddr_t *lladdr) } /*---------------------------------------------------------------------------*/ void -log_set_level(int level) +log_set_level(const char *module, int level) { if(level >= LOG_LEVEL_NONE && level <= LOG_LEVEL_DBG) { - curr_log_level = level; + 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(void) +log_get_level(const char *module) { - return curr_log_level; + 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 * diff --git a/core/sys/log.h b/core/sys/log.h index 48f0ba77b..6d0d1ff0f 100644 --- a/core/sys/log.h +++ b/core/sys/log.h @@ -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 <= MIN(LOG_LEVEL, curr_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 <= MIN(LOG_LEVEL, curr_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 <= MIN(LOG_LEVEL, curr_log_level)) { \ + if(level <= (LOG_LEVEL)) { \ if(LOG_WITH_COMPACT_ADDR) { \ log_6addr_compact(ipaddr); \ } else { \ @@ -135,9 +159,6 @@ #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) -/* The current log level */ -extern int curr_log_level; - #if NETSTACK_CONF_WITH_IPV6 /** @@ -170,15 +191,17 @@ 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(int 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(void); +int log_get_level(const char *module); /** * Returns a textual description of a log level diff --git a/examples/ipv6/rpl-tsch/node.c b/examples/ipv6/rpl-tsch/node.c index dfc386b41..36e67dc6d 100644 --- a/examples/ipv6/rpl-tsch/node.c +++ b/examples/ipv6/rpl-tsch/node.c @@ -72,7 +72,7 @@ PROCESS_THREAD(node_process, ev, data) #if WITH_SHELL serial_shell_init(); - log_set_level(LOG_LEVEL_WARN); + log_set_level("all", LOG_LEVEL_WARN); tsch_log_stop(); #endif /* WITH_SHELL */ diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index fa5cf2425..e1b99f576 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -157,12 +157,12 @@ #endif /* CONTIKI_TARGET_COOJA */ /* Logging */ -#define RPL_LOG_LEVEL LOG_LEVEL_INFO -#define TCPIP_LOG_LEVEL LOG_LEVEL_WARN -#define IPV6_LOG_LEVEL LOG_LEVEL_WARN -#define SICSLOWPAN_LOG_LEVEL LOG_LEVEL_WARN -#define MAC_LOG_LEVEL LOG_LEVEL_INFO -#define FRAMER_LOG_LEVEL LOG_LEVEL_WARN -#define TSCH_LOG_CONF_PER_SLOT 1 +#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__ */ diff --git a/examples/logging/project-conf.h b/examples/logging/project-conf.h index 39003b9c4..c35835afb 100644 --- a/examples/logging/project-conf.h +++ b/examples/logging/project-conf.h @@ -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