From 0ea63514e3bb2d8afecbac838cb92e7c7724576a Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Mon, 10 Jul 2017 17:45:07 +0200 Subject: [PATCH] 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 */