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 "net/mac/tsch/tsch.h"
51 #include "lib/ringbufindex.h"
52 #include "sys/log.h"
53 
54 #if TSCH_LOG_PER_SLOT
55 
56 PROCESS_NAME(tsch_pending_events_process);
57 
58 /* Check if TSCH_LOG_QUEUE_LEN is a power of two */
59 #if (TSCH_LOG_QUEUE_LEN & (TSCH_LOG_QUEUE_LEN - 1)) != 0
60 #error TSCH_LOG_QUEUE_LEN must be power of two
61 #endif
62 static struct ringbufindex log_ringbuf;
63 static struct tsch_log_t log_array[TSCH_LOG_QUEUE_LEN];
64 static int log_dropped = 0;
65 static int log_active = 0;
66 
67 /*---------------------------------------------------------------------------*/
68 /* Process pending log messages */
69 void
71 {
72  static int last_log_dropped = 0;
73  int16_t log_index;
74  /* Loop on accessing (without removing) a pending input packet */
75  if(log_dropped != last_log_dropped) {
76  printf("[WARN: TSCH-LOG ] logs dropped %u\n", log_dropped);
77  last_log_dropped = log_dropped;
78  }
79  while((log_index = ringbufindex_peek_get(&log_ringbuf)) != -1) {
80  struct tsch_log_t *log = &log_array[log_index];
81  if(log->link == NULL) {
82  printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link-NULL} ", log->asn.ms1b, log->asn.ls4b);
83  } else {
84  struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle);
85  printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link %2u %3u %3u %2u %2u ch %2u} ",
86  log->asn.ms1b, log->asn.ls4b,
87  log->link->slotframe_handle, sf ? sf->size.val : 0,
88  log->burst_count, log->link->timeslot + log->burst_count, log->link->channel_offset,
89  log->channel);
90  }
91  switch(log->type) {
92  case tsch_log_tx:
93  printf("%s-%u-%u tx ",
94  linkaddr_cmp(&log->tx.dest, &linkaddr_null) ? "bc" : "uc", log->tx.is_data, log->tx.sec_level);
96  printf("->");
97  log_lladdr_compact(&log->tx.dest);
98  printf(", len %3u, seq %3u, st %d %2d",
99  log->tx.datalen, log->tx.seqno, log->tx.mac_tx_status, log->tx.num_tx);
100  if(log->tx.drift_used) {
101  printf(", dr %3d", log->tx.drift);
102  }
103  printf("\n");
104  break;
105  case tsch_log_rx:
106  printf("%s-%u-%u rx ",
107  log->rx.is_unicast == 0 ? "bc" : "uc", log->rx.is_data, log->rx.sec_level);
108  log_lladdr_compact(&log->rx.src);
109  printf("->");
110  log_lladdr_compact(log->rx.is_unicast ? &linkaddr_node_addr : NULL);
111  printf(", len %3u, seq %3u",
112  log->rx.datalen, log->rx.seqno);
113  printf(", edr %3d", (int)log->rx.estimated_drift);
114  if(log->rx.drift_used) {
115  printf(", dr %3d\n", log->rx.drift);
116  } else {
117  printf("\n");
118  }
119  break;
120  case tsch_log_message:
121  printf("%s\n", log->message);
122  break;
123  }
124  /* Remove input from ringbuf */
125  ringbufindex_get(&log_ringbuf);
126  }
127 }
128 /*---------------------------------------------------------------------------*/
129 /* Prepare addition of a new log.
130  * Returns pointer to log structure if success, NULL otherwise */
131 struct tsch_log_t *
133 {
134  int log_index = ringbufindex_peek_put(&log_ringbuf);
135  if(log_index != -1) {
136  struct tsch_log_t *log = &log_array[log_index];
137  log->asn = tsch_current_asn;
138  log->link = current_link;
139  log->burst_count = tsch_current_burst_count;
140  log->channel = tsch_current_channel;
141  return log;
142  } else {
143  log_dropped++;
144  return NULL;
145  }
146 }
147 /*---------------------------------------------------------------------------*/
148 /* Actually add the previously prepared log */
149 void
150 tsch_log_commit(void)
151 {
152  if(log_active == 1) {
153  ringbufindex_put(&log_ringbuf);
154  process_poll(&tsch_pending_events_process);
155  }
156 }
157 /*---------------------------------------------------------------------------*/
158 /* Initialize log module */
159 void
160 tsch_log_init(void)
161 {
162  if(log_active == 0) {
163  ringbufindex_init(&log_ringbuf, TSCH_LOG_QUEUE_LEN);
164  log_active = 1;
165  }
166 }
167 /*---------------------------------------------------------------------------*/
168 /* Stop log module */
169 void
170 tsch_log_stop(void)
171 {
172  if(log_active == 1) {
174  log_active = 0;
175  }
176 }
177 
178 #endif /* TSCH_LOG_PER_SLOT */
179 /** @} */
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:143
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