49 #include "dev/watchdog.h" 54 #if MAC_CONF_WITH_TSCH 61 #if ROUTING_CONF_RPL_LITE 62 #include "net/routing/rpl-lite/rpl.h" 63 #elif ROUTING_CONF_RPL_CLASSIC 64 #include "net/routing/rpl-classic/rpl.h" 69 #define PING_TIMEOUT (5 * CLOCK_SECOND) 71 static struct uip_icmp6_echo_reply_notification echo_reply_notification;
72 static shell_output_func *curr_ping_output_func = NULL;
73 static struct process *curr_ping_process;
74 static uint8_t curr_ping_ttl;
75 static uint16_t curr_ping_datalen;
77 static shell_command_6top_sub_cmd_t sixtop_sub_cmd = NULL;
82 ds6_nbr_state_to_str(uint8_t state)
99 #if ROUTING_CONF_RPL_LITE 105 case DAG_INITIALIZED:
106 return "Initialized";
119 rpl_mop_to_str(
int mop)
122 case RPL_MOP_NO_DOWNWARD_ROUTES:
123 return "No downward routes";
124 case RPL_MOP_NON_STORING:
125 return "Non-storing";
126 case RPL_MOP_STORING_NO_MULTICAST:
128 case RPL_MOP_STORING_MULTICAST:
129 return "Storing+multicast";
136 rpl_ocp_to_str(
int ocp)
149 PT_THREAD(cmd_rpl_nbr(
struct pt *pt, shell_output_func
output,
char *args))
154 SHELL_OUTPUT(output,
"RPL neighbors: none\n");
157 SHELL_OUTPUT(output,
"RPL neighbors:\n");
161 SHELL_OUTPUT(output,
"%s\n", buf);
162 nbr = nbr_table_next(rpl_neighbors, nbr);
170 PT_THREAD(cmd_rpl_status(
struct pt *pt, shell_output_func output,
char *args))
174 SHELL_OUTPUT(output,
"RPL status:\n");
175 if(!curr_instance.used) {
176 SHELL_OUTPUT(output,
"-- Instance: None\n");
178 SHELL_OUTPUT(output,
"-- Instance: %u\n", curr_instance.instance_id);
180 SHELL_OUTPUT(output,
"-- DAG root\n");
182 SHELL_OUTPUT(output,
"-- DAG node\n");
184 SHELL_OUTPUT(output,
"-- DAG: ");
185 shell_output_6addr(output, &curr_instance.dag.dag_id);
186 SHELL_OUTPUT(output,
", version %u\n", curr_instance.dag.version);
187 SHELL_OUTPUT(output,
"-- Prefix: ");
188 shell_output_6addr(output, &curr_instance.dag.prefix_info.prefix);
189 SHELL_OUTPUT(output,
"/%u\n", curr_instance.dag.prefix_info.length);
190 SHELL_OUTPUT(output,
"-- MOP: %s\n", rpl_mop_to_str(curr_instance.mop));
191 SHELL_OUTPUT(output,
"-- OF: %s\n", rpl_ocp_to_str(curr_instance.of->ocp));
192 SHELL_OUTPUT(output,
"-- Hop rank increment: %u\n", curr_instance.min_hoprankinc);
193 SHELL_OUTPUT(output,
"-- Default lifetime: %lu seconds\n",
RPL_LIFETIME(curr_instance.default_lifetime));
195 SHELL_OUTPUT(output,
"-- State: %s\n", rpl_state_to_str(curr_instance.dag.state));
196 SHELL_OUTPUT(output,
"-- Preferred parent: ");
197 if(curr_instance.dag.preferred_parent) {
199 SHELL_OUTPUT(output,
" (last DTSN: %u)\n", curr_instance.dag.preferred_parent->dtsn);
201 SHELL_OUTPUT(output,
"None\n");
203 SHELL_OUTPUT(output,
"-- Rank: %u\n", curr_instance.dag.rank);
204 SHELL_OUTPUT(output,
"-- Lowest rank: %u (%u)\n", curr_instance.dag.lowest_rank, curr_instance.max_rankinc);
205 SHELL_OUTPUT(output,
"-- DTSN out: %u\n", curr_instance.dtsn_out);
206 SHELL_OUTPUT(output,
"-- DAO sequence: last sent %u, last acked %u\n",
207 curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_last_acked_seqno);
208 SHELL_OUTPUT(output,
"-- Trickle timer: current %u, min %u, max %u, redundancy %u\n",
209 curr_instance.dag.dio_intcurrent, curr_instance.dio_intmin,
210 curr_instance.dio_intmin + curr_instance.dio_intdoubl, curr_instance.dio_redundancy);
219 echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen)
221 if(curr_ping_output_func != NULL) {
222 curr_ping_output_func = NULL;
224 curr_ping_datalen = datalen;
230 PT_THREAD(cmd_ping(
struct pt *pt, shell_output_func output,
char *args))
232 static uip_ipaddr_t remote_addr;
233 static struct etimer timeout_timer;
238 SHELL_ARGS_INIT(args, next_args);
241 SHELL_ARGS_NEXT(args, next_args);
243 SHELL_OUTPUT(output,
"Destination IPv6 address is not specified\n");
246 SHELL_OUTPUT(output,
"Invalid IPv6 address: %s\n", args);
250 SHELL_OUTPUT(output,
"Pinging ");
251 shell_output_6addr(output, &remote_addr);
252 SHELL_OUTPUT(output,
"\n");
256 curr_ping_output_func =
output;
261 if(curr_ping_output_func != NULL) {
262 SHELL_OUTPUT(output,
"Timeout\n");
263 curr_ping_output_func = NULL;
265 SHELL_OUTPUT(output,
"Received ping reply from ");
266 shell_output_6addr(output, &remote_addr);
267 SHELL_OUTPUT(output,
", len %u, ttl %u, delay %lu ms\n",
275 shell_output_log_levels(shell_output_func output)
278 SHELL_OUTPUT(output,
"Log levels:\n");
279 while(all_modules[i].name != NULL) {
280 SHELL_OUTPUT(output,
"-- %-10s: %u (%s)\n",
282 *all_modules[i].curr_log_level,
289 PT_THREAD(cmd_log(
struct pt *pt, shell_output_func output,
char *args))
291 static int prev_level;
299 SHELL_ARGS_INIT(args, next_args);
302 SHELL_ARGS_NEXT(args, next_args);
305 if(module == NULL || (strcmp(
"all", module) && prev_level == -1)) {
306 SHELL_OUTPUT(output,
"Invalid first argument: %s\n", module)
307 shell_output_log_levels(output);
312 SHELL_ARGS_NEXT(args, next_args);
316 level = (int)strtol(args, &ptr, 10);
318 if((level == 0 && args == ptr)
319 || level < LOG_LEVEL_NONE || level > LOG_LEVEL_DBG) {
320 SHELL_OUTPUT(output,
"Invalid second argument: %s\n", args);
325 if(level != prev_level) {
327 #if MAC_CONF_WITH_TSCH && TSCH_LOG_PER_SLOT 328 if(!strcmp(module,
"mac") || !strcmp(module,
"all")) {
329 if(level >= LOG_LEVEL_DBG) {
331 SHELL_OUTPUT(output,
"TSCH logging started\n");
334 SHELL_OUTPUT(output,
"TSCH logging stopped\n");
340 shell_output_log_levels(output);
346 PT_THREAD(cmd_help(
struct pt *pt, shell_output_func output,
char *args))
348 struct shell_command_t *cmd_ptr;
352 SHELL_OUTPUT(output,
"Available commands:\n");
353 cmd_ptr = shell_commands;
354 while(cmd_ptr->name != NULL) {
355 SHELL_OUTPUT(output,
"%s\n", cmd_ptr->help);
361 #if UIP_CONF_IPV6_RPL 364 PT_THREAD(cmd_rpl_set_root(
struct pt *pt, shell_output_func output,
char *args))
367 static uip_ipaddr_t prefix;
372 SHELL_ARGS_INIT(args, next_args);
375 SHELL_ARGS_NEXT(args, next_args);
377 if(!strcmp(args,
"1")) {
379 }
else if(!strcmp(args,
"0")) {
382 SHELL_OUTPUT(output,
"Invalid argument: %s\n", args);
387 SHELL_ARGS_NEXT(args, next_args);
390 SHELL_OUTPUT(output,
"Invalid Prefix: %s\n", args);
394 uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
399 SHELL_OUTPUT(output,
"Setting as DAG root with prefix ");
400 shell_output_6addr(output, &prefix);
401 SHELL_OUTPUT(output,
"/64\n");
405 SHELL_OUTPUT(output,
"Node is already a DAG root\n");
409 SHELL_OUTPUT(output,
"Setting as non-root node: leaving DAG\n");
412 SHELL_OUTPUT(output,
"Node is not a DAG root\n");
420 PT_THREAD(cmd_rpl_global_repair(
struct pt *pt, shell_output_func output,
char *args))
424 SHELL_OUTPUT(output,
"Triggering routing global repair\n")
425 NETSTACK_ROUTING.global_repair("Shell");
431 PT_THREAD(cmd_rpl_local_repair(struct pt *pt, shell_output_func output,
char *args))
435 SHELL_OUTPUT(output,
"Triggering routing local repair\n");
441 #if ROUTING_CONF_RPL_LITE 443 PT_THREAD(cmd_rpl_refresh_routes(
struct pt *pt, shell_output_func output,
char *args))
447 SHELL_OUTPUT(output,
"Triggering routes refresh\n")
456 PT_THREAD(cmd_ipaddr(
struct pt *pt, shell_output_func output,
char *args))
463 SHELL_OUTPUT(output,
"Node IPv6 addresses:\n");
464 for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
468 SHELL_OUTPUT(output,
"-- ");
469 shell_output_6addr(output, &
uip_ds6_if.addr_list[i].ipaddr);
470 SHELL_OUTPUT(output,
"\n");
479 PT_THREAD(cmd_ip_neighbors(
struct pt *pt, shell_output_func output,
char *args))
485 nbr = uip_ds6_nbr_head();
487 SHELL_OUTPUT(output,
"Node IPv6 neighbors: none\n");
491 SHELL_OUTPUT(output,
"Node IPv6 neighbors:\n");
493 SHELL_OUTPUT(output,
"-- ");
494 shell_output_6addr(output, uip_ds6_nbr_get_ipaddr(nbr));
495 SHELL_OUTPUT(output,
" <-> ");
497 SHELL_OUTPUT(output,
", router %u, state %s ",
498 nbr->isrouter, ds6_nbr_state_to_str(nbr->state));
499 SHELL_OUTPUT(output,
"\n");
500 nbr = uip_ds6_nbr_next(nbr);
506 #if MAC_CONF_WITH_TSCH 509 PT_THREAD(cmd_tsch_set_coordinator(
struct pt *pt, shell_output_func output,
char *args))
512 static int is_secured;
517 SHELL_ARGS_INIT(args, next_args);
520 SHELL_ARGS_NEXT(args, next_args);
522 if(!strcmp(args,
"1")) {
524 }
else if(!strcmp(args,
"0")) {
527 SHELL_OUTPUT(output,
"Invalid first argument: %s\n", args);
532 SHELL_ARGS_NEXT(args, next_args);
534 if(!strcmp(args,
"1")) {
535 #if LLSEC802154_ENABLED 538 SHELL_OUTPUT(output,
"Security is not compiled in.\n");
541 }
else if(!strcmp(args,
"0")) {
544 SHELL_OUTPUT(output,
"Invalid second argument: %s\n", args);
551 SHELL_OUTPUT(output,
"Setting as TSCH %s (%s)\n",
552 is_on ?
"coordinator" :
"non-coordinator", is_secured ?
"secured" :
"non-secured");
561 PT_THREAD(cmd_tsch_status(
struct pt *pt, shell_output_func output,
char *args))
565 SHELL_OUTPUT(output,
"TSCH status:\n");
567 SHELL_OUTPUT(output,
"-- Is coordinator: %u\n", tsch_is_coordinator);
568 SHELL_OUTPUT(output,
"-- Is associated: %u\n", tsch_is_associated);
569 if(tsch_is_associated) {
571 SHELL_OUTPUT(output,
"-- PAN ID: 0x%x\n", frame802154_get_pan_id());
572 SHELL_OUTPUT(output,
"-- Is PAN secured: %u\n", tsch_is_pan_secured);
573 SHELL_OUTPUT(output,
"-- Join priority: %u\n", tsch_join_priority);
574 SHELL_OUTPUT(output,
"-- Time source: ");
577 SHELL_OUTPUT(output,
"\n");
579 SHELL_OUTPUT(output,
"none\n");
581 SHELL_OUTPUT(output,
"-- Last synchronized: %lu seconds ago\n", (
clock_time() - last_sync_time) /
CLOCK_SECOND);
590 PT_THREAD(cmd_routes(
struct pt *pt, shell_output_func output,
char *args))
597 SHELL_OUTPUT(output,
"Default route:\n");
598 default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose());
599 if(default_route != NULL) {
600 SHELL_OUTPUT(output,
"-- ");
601 shell_output_6addr(output, &default_route->ipaddr);
602 if(default_route->lifetime.interval != 0) {
603 SHELL_OUTPUT(output,
" (lifetime: %lu seconds)\n", (
unsigned long)default_route->lifetime.interval);
605 SHELL_OUTPUT(output,
" (lifetime: infinite)\n");
608 SHELL_OUTPUT(output,
"-- None\n");
611 #if UIP_CONF_IPV6_RPL 617 while(link != NULL) {
620 SHELL_OUTPUT(output,
"-- %s\n", buf);
624 SHELL_OUTPUT(output,
"No routing links\n");
628 #if (UIP_MAX_ROUTES != 0) 629 if(uip_ds6_route_num_routes() > 0) {
632 SHELL_OUTPUT(output,
"Routing entries (%u in total):\n", uip_ds6_route_num_routes());
633 route = uip_ds6_route_head();
634 while(route != NULL) {
635 SHELL_OUTPUT(output,
"-- ");
636 shell_output_6addr(output, &route->ipaddr);
637 SHELL_OUTPUT(output,
" via ");
638 shell_output_6addr(output, uip_ds6_route_nexthop(route));
639 if((
unsigned long)route->state.lifetime != 0xFFFFFFFF) {
640 SHELL_OUTPUT(output,
" (lifetime: %lu seconds)\n", (
unsigned long)route->state.lifetime);
642 SHELL_OUTPUT(output,
" (lifetime: infinite)\n");
644 route = uip_ds6_route_next(route);
647 SHELL_OUTPUT(output,
"No routing entries\n");
655 PT_THREAD(cmd_reboot(
struct pt *pt, shell_output_func output,
char *args))
658 SHELL_OUTPUT(output,
"rebooting\n");
662 #if MAC_CONF_WITH_TSCH 665 PT_THREAD(cmd_tsch_schedule(
struct pt *pt, shell_output_func output,
char *args))
678 SHELL_OUTPUT(output,
"TSCH schedule: no slotframe\n");
680 SHELL_OUTPUT(output,
"TSCH schedule:\n");
684 SHELL_OUTPUT(output,
"-- Slotframe: handle %u, size %u, links:\n", sf->handle, sf->size.val);
687 SHELL_OUTPUT(output,
"---- Options %02x, type %u, timeslot %u, channel offset %u, address ",
688 l->link_options, l->link_type, l->timeslot, l->channel_offset);
690 SHELL_OUTPUT(output,
"\n");
703 shell_commands_set_6top_sub_cmd(shell_command_6top_sub_cmd_t sub_cmd)
705 sixtop_sub_cmd = sub_cmd;
709 PT_THREAD(cmd_6top(
struct pt *pt, shell_output_func output,
char *args))
715 SHELL_ARGS_INIT(args, next_args);
717 if(sixtop_sub_cmd == NULL) {
718 SHELL_OUTPUT(output,
"6top command is unavailable:\n");
720 SHELL_OUTPUT(output,
"6top: ");
721 sixtop_sub_cmd(output, args);
723 SHELL_ARGS_NEXT(args, next_args);
737 struct shell_command_t shell_commands[] = {
738 {
"help", cmd_help,
"'> help': Shows this help" },
739 {
"reboot", cmd_reboot,
"'> reboot': Reboot the board by watchdog_reboot()" },
740 {
"ip-addr", cmd_ipaddr,
"'> ip-addr': Shows all IPv6 addresses" },
741 {
"ip-nbr", cmd_ip_neighbors,
"'> ip-nbr': Shows all IPv6 neighbors" },
742 {
"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." },
743 {
"ping", cmd_ping,
"'> ping addr': Pings the IPv6 address 'addr'" },
744 #if UIP_CONF_IPV6_RPL 745 {
"rpl-set-root", cmd_rpl_set_root,
"'> rpl-set-root 0/1 [prefix]': Sets node as root (1) or not (0). A /64 prefix can be optionally specified." },
746 {
"rpl-local-repair", cmd_rpl_local_repair,
"'> rpl-local-repair': Triggers a RPL local repair" },
747 #if ROUTING_CONF_RPL_LITE 748 {
"rpl-refresh-routes", cmd_rpl_refresh_routes,
"'> rpl-refresh-routes': Refreshes all routes through a DTSN increment" },
750 {
"rpl-global-repair", cmd_rpl_global_repair,
"'> rpl-global-repair': Triggers a RPL global repair" },
752 #if ROUTING_CONF_RPL_LITE 753 {
"rpl-status", cmd_rpl_status,
"'> rpl-status': Shows a summary of the current RPL state" },
754 {
"rpl-nbr", cmd_rpl_nbr,
"'> rpl-nbr': Shows the RPL neighbor table" },
756 {
"routes", cmd_routes,
"'> routes': Shows the route entries" },
757 #if MAC_CONF_WITH_TSCH 758 {
"tsch-set-coordinator", cmd_tsch_set_coordinator,
"'> tsch-set-coordinator 0/1 [0/1]': Sets node as coordinator (1) or not (0). Second, optional parameter: enable (1) or disable (0) security." },
759 {
"tsch-schedule", cmd_tsch_schedule,
"'> tsch-schedule': Shows the current TSCH schedule" },
760 {
"tsch-status", cmd_tsch_status,
"'> tsch-status': Shows a summary of the current TSCH state" },
763 {
"6top", cmd_6top,
"'> 6top help': Shows 6top command usage" },
765 { NULL, NULL, NULL },
#define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7)
Construct an IPv6 address from eight 16-bit words.
An entry in the default router list.
Header file for ICMPv6 message and error handing (RFC 4443)
Main header file for the Contiki shell
uip_ipaddr_t * rpl_neighbor_get_ipaddr(rpl_nbr_t *nbr)
Returns a neighbor's (link-local) IPv6 address.
void shell_commands_init(void)
Initializes Shell-commands module.
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
struct tsch_slotframe * tsch_schedule_slotframe_next(struct tsch_slotframe *sf)
Access the next item in the list of slotframes.
int uip_sr_num_nodes(void)
Tells how many nodes are currently stored in the graph.
void shell_output_lladdr(shell_output_func output, const linkaddr_t *lladdr)
Prints a link-layer address.
void tsch_log_init(void)
Initialize log module.
watchdog_reboot()
Keeps control until the WDT throws a reset signal.
TSCH neighbor information.
802.15.4e slotframe (contains links)
Main header file for the Contiki shell
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
struct tsch_neighbor * tsch_queue_get_time_source(void)
Get the TSCH time source (we currently assume there is only one)
Common functionality of 802.15.4-compliant llsec_drivers.
#define PT_WAIT_UNTIL(pt, condition)
Block and wait until condition is true.
#define RPL_LIFETIME(lifetime)
Compute lifetime, accounting for the lifetime unit.
#define ICMP6_ECHO_REQUEST
Echo request.
int(* root_start)(void)
Set the node as root and start a network.
int rpl_neighbor_count(void)
Returns the number of nodes in the RPL neighbor table.
static uint8_t output(const linkaddr_t *localdest)
Take an IP packet and format it to be sent on an 802.15.4 network using 6lowpan.
Header file for IPv6-related data structures.
void tsch_log_stop(void)
Stop logging module.
void(* root_set_prefix)(uip_ipaddr_t *prefix, uip_ipaddr_t *iid)
Set the prefix, for nodes that will operate as root.
uip_sr_node_t * uip_sr_node_next(uip_sr_node_t *item)
Returns the next element of the non-storing node list.
#define PROCESS_CURRENT()
Get a pointer to the currently running process.
An entry in the routing table.
void log_set_level(const char *module, int level)
Sets a log level at run-time.
#define CLOCK_SECOND
A second, measured in system clock time.
Header file for the IP address manipulation library.
void uip_icmp6_echo_reply_callback_add(struct uip_icmp6_echo_reply_notification *n, uip_icmp6_echo_reply_callback_t c)
Add a callback function for ping replies.
#define PT_END(pt)
Declare the end of a protothread.
int(* node_is_root)(void)
Tells whether the node is a network root or not.
void process_poll(struct process *p)
Request a process to be polled.
void * list_head(list_t list)
Get a pointer to the first element of a list.
uip_sr_node_t * uip_sr_node_head(void)
Returns the head of the non-storing node list.
rpl_dag_state
RPL DAG states.
Routing driver header file
All information related to a RPL neighbor.
Main API declarations for TSCH.
clock_time_t clock_time(void)
Get the current clock time.
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
int tsch_is_locked(void)
Checks if the TSCH lock is set.
struct tsch_slotframe * tsch_schedule_slotframe_head(void)
Access the first item in the list of slotframes.
long int tsch_adaptive_timesync_get_drift_ppm(void)
Gives the estimated clock drift w.r.t.
#define PT_EXIT(pt)
Exit the protothread.
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
#define PT_THREAD(name_args)
Declaration of a protothread.
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
void(* leave_network)(void)
Leave the network the node is part of.
int uip_sr_link_snprint(char *buf, int buflen, uip_sr_node_t *link)
Print a textual description of a source routing link.
Header file for the uIP TCP/IP stack.
const char * log_level_to_str(int level)
Returns a textual description of a log level.
int log_get_level(const char *module)
Returns the current log level.
uip_ds6_netif_t uip_ds6_if
The single interface.
void rpl_refresh_routes(const char *str)
Triggers a route fresh via DTSN increment.
void(* local_repair)(const char *str)
Triggers a RPL local topology repair.
void tsch_set_pan_secured(int enable)
Enable/disable security.
An IEEE 802.15.4-2015 TSCH link (also called cell or slot)
void uip_icmp6_send(const uip_ipaddr_t *dest, int type, int code, int payload_len)
Send an icmpv6 message.
#define uiplib_ipaddrconv
Convert a textual representation of an IP address to a numerical representation.
Header file for the logging system
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
void * list_item_next(void *item)
Get the next item following this item.
int rpl_neighbor_snprint(char *buf, int buflen, rpl_nbr_t *nbr)
Print a textual description of RPL neighbor into a string.
A node in a source routing graph, stored at the root and representing all child-parent relationship...
void tsch_set_coordinator(int enable)
Set the node as PAN coordinator.
An entry in the nbr cache.