Contiki-NG
tsch-log.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, SICS Swedish ICT.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Log functions for TSCH, meant for logging from interrupt
36  * during a timeslot operation. Saves ASN, slot and link information
37  * and adds the log to a ringbuf for later printout.
38  * \author
39  * Simon Duquennoy <simonduq@sics.se>
40  *
41  */
42 
43 /**
44  * \addtogroup tsch
45  * @{
46 */
47 
48 #include "contiki.h"
49 #include <stdio.h>
50 #include <inttypes.h>
51 #include "net/mac/tsch/tsch.h"
52 #include "lib/ringbufindex.h"
53 #include "sys/log.h"
54 
55 #if TSCH_LOG_PER_SLOT
56 
57 PROCESS_NAME(tsch_pending_events_process);
58 
59 /* Check if TSCH_LOG_QUEUE_LEN is a power of two */
60 #if (TSCH_LOG_QUEUE_LEN & (TSCH_LOG_QUEUE_LEN - 1)) != 0
61 #error TSCH_LOG_QUEUE_LEN must be power of two
62 #endif
63 static struct ringbufindex log_ringbuf;
64 static struct tsch_log_t log_array[TSCH_LOG_QUEUE_LEN];
65 static int log_dropped = 0;
66 static int log_active = 0;
67 
68 /*---------------------------------------------------------------------------*/
69 /* Process pending log messages */
70 void
72 {
73  static int last_log_dropped = 0;
74  int16_t log_index;
75  /* Loop on accessing (without removing) a pending input packet */
76  if(log_dropped != last_log_dropped) {
77  printf("[WARN: TSCH-LOG ] logs dropped %u\n", log_dropped);
78  last_log_dropped = log_dropped;
79  }
80  while((log_index = ringbufindex_peek_get(&log_ringbuf)) != -1) {
81  struct tsch_log_t *log = &log_array[log_index];
82  if(log->link == NULL) {
83  printf("[INFO: TSCH-LOG ] {asn %02x.%08"PRIx32" link-NULL} ", log->asn.ms1b, log->asn.ls4b);
84  } else {
85  struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle);
86  printf("[INFO: TSCH-LOG ] {asn %02x.%08"PRIx32" link %2u %3u %3u %2u %2u ch %2u} ",
87  log->asn.ms1b, log->asn.ls4b,
88  log->link->slotframe_handle, sf ? sf->size.val : 0,
89  log->burst_count, log->link->timeslot + log->burst_count, log->channel_offset,
90  log->channel);
91  }
92  switch(log->type) {
93  case tsch_log_tx:
94  printf("%s-%u-%u tx ",
95  linkaddr_cmp(&log->tx.dest, &linkaddr_null) ? "bc" : "uc", log->tx.is_data, log->tx.sec_level);
97  printf("->");
98  log_lladdr_compact(&log->tx.dest);
99  printf(", len %3u, seq %3u, st %d %2d",
100  log->tx.datalen, log->tx.seqno, log->tx.mac_tx_status, log->tx.num_tx);
101  if(log->tx.drift_used) {
102  printf(", dr %3d", log->tx.drift);
103  }
104  printf("\n");
105  break;
106  case tsch_log_rx:
107  printf("%s-%u-%u rx ",
108  log->rx.is_unicast == 0 ? "bc" : "uc", log->rx.is_data, log->rx.sec_level);
109  log_lladdr_compact(&log->rx.src);
110  printf("->");
111  log_lladdr_compact(log->rx.is_unicast ? &linkaddr_node_addr : NULL);
112  printf(", len %3u, seq %3u",
113  log->rx.datalen, log->rx.seqno);
114  printf(", edr %3d", (int)log->rx.estimated_drift);
115  if(log->rx.drift_used) {
116  printf(", dr %3d\n", log->rx.drift);
117  } else {
118  printf("\n");
119  }
120  break;
121  case tsch_log_message:
122  printf("%s\n", log->message);
123  break;
124  }
125  /* Remove input from ringbuf */
126  ringbufindex_get(&log_ringbuf);
127  }
128 }
129 /*---------------------------------------------------------------------------*/
130 /* Prepare addition of a new log.
131  * Returns pointer to log structure if success, NULL otherwise */
132 struct tsch_log_t *
134 {
135  int log_index = ringbufindex_peek_put(&log_ringbuf);
136  if(log_index != -1) {
137  struct tsch_log_t *log = &log_array[log_index];
138  log->asn = tsch_current_asn;
139  log->link = current_link;
140  log->burst_count = tsch_current_burst_count;
141  log->channel = tsch_current_channel;
142  log->channel_offset = tsch_current_channel_offset;
143  return log;
144  } else {
145  log_dropped++;
146  return NULL;
147  }
148 }
149 /*---------------------------------------------------------------------------*/
150 /* Actually add the previously prepared log */
151 void
152 tsch_log_commit(void)
153 {
154  if(log_active == 1) {
155  ringbufindex_put(&log_ringbuf);
156  process_poll(&tsch_pending_events_process);
157  }
158 }
159 /*---------------------------------------------------------------------------*/
160 /* Initialize log module */
161 void
162 tsch_log_init(void)
163 {
164  if(log_active == 0) {
165  ringbufindex_init(&log_ringbuf, TSCH_LOG_QUEUE_LEN);
166  log_active = 1;
167  }
168 }
169 /*---------------------------------------------------------------------------*/
170 /* Stop log module */
171 void
172 tsch_log_stop(void)
173 {
174  if(log_active == 1) {
176  log_active = 0;
177  }
178 }
179 
180 #endif /* TSCH_LOG_PER_SLOT */
181 /** @} */
void ringbufindex_init(struct ringbufindex *r, uint8_t size)
Initialize a ring buffer.
Definition: ringbufindex.c:50
void tsch_log_process_pending(void)
Process pending log messages.
Header file for the ringbufindex library
Structure for a log.
Definition: tsch-log.h:76
int ringbufindex_peek_get(const struct ringbufindex *r)
Return the index of the first element which will be removed if calling ringbufindex_get.
Definition: ringbufindex.c:115
void tsch_log_init(void)
Initialize log module.
802.15.4e slotframe (contains links)
Definition: tsch-types.h:84
struct tsch_log_t * tsch_log_prepare_add(void)
Prepare addition of a new log.
const linkaddr_t linkaddr_null
The null link-layer address.
void log_lladdr_compact(const linkaddr_t *lladdr)
Logs a link-layer address with a compact format.
Definition: log.c:145
void tsch_log_stop(void)
Stop logging module.
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition: linkaddr.c:48
struct tsch_slotframe * tsch_schedule_get_slotframe_by_handle(uint16_t handle)
Looks up a slotframe by handle.
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
#define PROCESS_NAME(name)
Declare the name of a process.
Definition: process.h:286
Main API declarations for TSCH.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
Definition: linkaddr.c:69
void tsch_log_commit(void)
Actually add the previously prepared log.
int ringbufindex_get(struct ringbufindex *r)
Remove the first element and return its index.
Definition: ringbufindex.c:90
int ringbufindex_peek_put(const struct ringbufindex *r)
Check if there is space to put an element.
Definition: ringbufindex.c:78
Header file for the logging system
int ringbufindex_put(struct ringbufindex *r)
Put one element to the ring buffer.
Definition: ringbufindex.c:58