From 75f3a154ad05439441d1e41c7a4909f5f275af59 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Thu, 6 Jul 2017 19:43:44 +0200 Subject: [PATCH] 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__ */