Blame view

RIOT/sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h 10.5 KB
a752c7ab   elopes   add first test an...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
  /*
   * Copyright (C) 2015 Daniel Krebs
   *               2016 INRIA
   *
   * This file is subject to the terms and conditions of the GNU Lesser
   * General Public License v2.1. See the file LICENSE in the top level
   * directory for more details.
   */
  
  /**
   * @ingroup     net_gnrc_lwmac
   * @{
   *
   * @file
   * @brief       Interface definition for internal functions of LWMAC protocol
   *
   * @author      Daniel Krebs <github@daniel-krebs.net>
   * @author      Shuguo Zhuo  <shuguo.zhuo@inria.fr>
   */
  
  #ifndef LWMAC_INTERNAL_H
  #define LWMAC_INTERNAL_H
  
  #include <stdint.h>
  
  #include "periph/rtt.h"
  #include "net/gnrc/netdev.h"
  #include "net/gnrc/mac/types.h"
  #include "net/gnrc/lwmac/types.h"
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /**
   * @brief   Flag to track if the sender can continue to transmit packet to
   *          the receiver in its TX procedure.
   *
   * LWMAC supports burst transmission based on the pending-bit technique.
   * Namely, if the sender has multi packets for the same receiver, it can
   * successively transmit its packets back to back with this flag set up,
   * with the awareness that the receiver will also keep awake for receptions.
   */
  #define GNRC_NETDEV_LWMAC_TX_CONTINUE          (0x0008U)
  
  /**
   * @brief   Flag to track if the sender should quit Tx in current cycle.
   *
   * This flag is mainly for collision avoidance. In case a node overhears
   * ongoing broadcast packets stream or other ongoing transmissions of
   * other communication pairs during its wake-up period, it sets up this
   * flag, which quits all its potential transmission attempts in this current
   * cycle (started by the wake-up period), thus not to collide with other
   * (neighbor) nodes' transmissions.
   */
  #define GNRC_NETDEV_LWMAC_QUIT_TX              (0x0010U)
  
  /**
   * @brief   Flag to track if the device need to reselect a new wake-up phase.
   *
   * This flag is mainly for potential collision avoidance. In multi-hop scenario,
   * it could be dangerous that a sender's wake-up phase is close to its receiver's,
   * which may lead to collisions when the sender is sending to the receiver while
   * the sender's son nodes are also sending to the sender. To avoid this, in case a
   * sender finds its phase close to its receiver's, it sets up this flag and then
   * randomly reselects a new wake-up phase.
   */
  #define GNRC_NETDEV_LWMAC_PHASE_BACKOFF        (0x0020U)
  
  /**
   * @brief   Flag to track if the device needs to quit the wake-up (listening) procedure.
   *
   * LWMAC adopts an auto wake-up extension scheme. That is, normally, after each data
   * reception in the wake-up period, it extends the wake-up period to another basic
   * duration, thus to receive more potential incoming packets, which is also correlated to
   * the pending-bit transmission scheme to support burst transmissions to boost throughput.
   * However, in some situations, like receiving broadcast (stream) packet, the receiver
   * should immediately goto sleep (by setting up this flag) after one reception, thus not
   * to receive duplicate broadcast packets.
   */
  #define GNRC_NETDEV_LWMAC_QUIT_RX              (0x0040U)
  
  /**
   * @brief Type to pass information about parsing.
   */
  typedef struct {
      gnrc_lwmac_hdr_t *header;      /**< LWMAC header of packet */
      gnrc_lwmac_l2_addr_t src_addr; /**< copied source address of packet  */
      gnrc_lwmac_l2_addr_t dst_addr; /**< copied destination address of packet */
  } gnrc_lwmac_packet_info_t;
  
  /**
   * @brief Next RTT event must be at least this far in the future.
   *
   * When setting an RTT alarm to short in the future it could be possible that
   * the counter already passed the calculated alarm before it could be set.
   */
  #define GNRC_LWMAC_RTT_EVENT_MARGIN_TICKS    (RTT_MS_TO_TICKS(2))
  
  /**
   * @brief set the TX-continue flag of the device
   *
   * @param[in] dev          ptr to netdev device
   * @param[in] tx_continue  value for LWMAC tx-continue flag
   *
   */
  static inline void gnrc_netdev_lwmac_set_tx_continue(gnrc_netdev_t *dev, bool tx_continue)
  {
      if (tx_continue) {
          dev->mac_info |= GNRC_NETDEV_LWMAC_TX_CONTINUE;
      }
      else {
          dev->mac_info &= ~GNRC_NETDEV_LWMAC_TX_CONTINUE;
      }
  }
  
  /**
   * @brief get the TX-continue flag of the device
   *
   * @param[in] dev          ptr to netdev device
   *
   * @return                 true if tx continue
   * @return                 false if tx will continue
   */
  static inline bool gnrc_netdev_lwmac_get_tx_continue(gnrc_netdev_t *dev)
  {
      return (dev->mac_info & GNRC_NETDEV_LWMAC_TX_CONTINUE);
  }
  
  /**
   * @brief set the quit-TX flag of the device
   *
   * @param[in] dev          ptr to netdev device
   * @param[in] quit_tx      value for LWMAC quit-TX flag
   *
   */
  static inline void gnrc_netdev_lwmac_set_quit_tx(gnrc_netdev_t *dev, bool quit_tx)
  {
      if (quit_tx) {
          dev->mac_info |= GNRC_NETDEV_LWMAC_QUIT_TX;
      }
      else {
          dev->mac_info &= ~GNRC_NETDEV_LWMAC_QUIT_TX;
      }
  }
  
  /**
   * @brief get the quit-TX flag of the device
   *
   * @param[in] dev          ptr to netdev device
   *
   * @return                 true if quit tx
   * @return                 false if will not quit tx
   */
  static inline bool gnrc_netdev_lwmac_get_quit_tx(gnrc_netdev_t *dev)
  {
      return (dev->mac_info & GNRC_NETDEV_LWMAC_QUIT_TX);
  }
  
  /**
   * @brief set the phase-backoff flag of the device
   *
   * @param[in] dev          ptr to netdev device
   * @param[in] backoff      value for LWMAC phase-backoff flag
   *
   */
  static inline void gnrc_netdev_lwmac_set_phase_backoff(gnrc_netdev_t *dev, bool backoff)
  {
      if (backoff) {
          dev->mac_info |= GNRC_NETDEV_LWMAC_PHASE_BACKOFF;
      }
      else {
          dev->mac_info &= ~GNRC_NETDEV_LWMAC_PHASE_BACKOFF;
      }
  }
  
  /**
   * @brief get the phase-backoff of the device
   *
   * @param[in] dev          ptr to netdev device
   *
   * @return                 true if will run phase-backoff
   * @return                 false if will not run phase-backoff
   */
  static inline bool gnrc_netdev_lwmac_get_phase_backoff(gnrc_netdev_t *dev)
  {
      return (dev->mac_info & GNRC_NETDEV_LWMAC_PHASE_BACKOFF);
  }
  
  /**
   * @brief set the quit-RX flag of the device
   *
   * @param[in] dev          ptr to netdev device
   * @param[in] quit_rx      value for LWMAC quit-Rx flag
   *
   */
  static inline void gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev_t *dev, bool quit_rx)
  {
      if (quit_rx) {
          dev->mac_info |= GNRC_NETDEV_LWMAC_QUIT_RX;
      }
      else {
          dev->mac_info &= ~GNRC_NETDEV_LWMAC_QUIT_RX;
      }
  }
  
  /**
   * @brief get the quit-RX flag of the device
   *
   * @param[in] dev          ptr to netdev device
   *
   * @return                 true if will quit rx
   * @return                 false if will not quit rx
   */
  static inline bool gnrc_netdev_lwmac_get_quit_rx(gnrc_netdev_t *dev)
  {
      return (dev->mac_info & GNRC_NETDEV_LWMAC_QUIT_RX);
  }
  
  /**
   * @brief set the duty-cycle-active flag of LWMAC
   *
   * @param[in] dev          ptr to netdev device
   * @param[in] active       value for LWMAC duty-cycle-active flag
   *
   */
  static inline void gnrc_netdev_lwmac_set_dutycycle_active(gnrc_netdev_t *dev, bool active)
  {
      if (active) {
          dev->lwmac.lwmac_info |= GNRC_LWMAC_DUTYCYCLE_ACTIVE;
      }
      else {
          dev->lwmac.lwmac_info &= ~GNRC_LWMAC_DUTYCYCLE_ACTIVE;
      }
  }
  
  /**
   * @brief get the duty-cycle-active flag of LWMAC
   *
   * @param[in] dev          ptr to netdev device
   *
   * @return                 true if active
   * @return                 false if not active
   */
  static inline bool gnrc_netdev_lwmac_get_dutycycle_active(gnrc_netdev_t *dev)
  {
      return (dev->lwmac.lwmac_info & GNRC_LWMAC_DUTYCYCLE_ACTIVE);
  }
  
  /**
   * @brief set the needs-rescheduling flag of LWMAC
   *
   * @param[in] dev          ptr to netdev device
   * @param[in] reschedule   value for LWMAC needs-rescheduling flag
   *
   */
  static inline void gnrc_netdev_lwmac_set_reschedule(gnrc_netdev_t *dev, bool reschedule)
  {
      if (reschedule) {
          dev->lwmac.lwmac_info |= GNRC_LWMAC_NEEDS_RESCHEDULE;
      }
      else {
          dev->lwmac.lwmac_info &= ~GNRC_LWMAC_NEEDS_RESCHEDULE;
      }
  }
  
  /**
   * @brief get the needs-rescheduling flag of LWMAC
   *
   * @param[in] dev          ptr to netdev device
   *
   * @return                 true if needs rescheduling
   * @return                 false if no need for rescheduling
   */
  static inline bool gnrc_netdev_lwmac_get_reschedule(gnrc_netdev_t *dev)
  {
      return (dev->lwmac.lwmac_info & GNRC_LWMAC_NEEDS_RESCHEDULE);
  }
  
  /**
   * @brief Parse an incoming packet and extract important information.
   *
   *        Copies addresses into @p info, but header points inside @p pkt.
   *
   * @param[in]   pkt             packet that will be parsed
   * @param[out]  info            structure that will hold parsed information
   *
   * @return                      0 if correctly parsed
   * @return                      <0 on error
   */
  int _gnrc_lwmac_parse_packet(gnrc_pktsnip_t *pkt, gnrc_lwmac_packet_info_t *info);
  
  /**
   * @brief Shortcut to get the state of netdev.
   *
   * @param[in]   gnrc_netdev    gnrc_netdev structure
   *
   * @return                     state of netdev
   */
  netopt_state_t _gnrc_lwmac_get_netdev_state(gnrc_netdev_t *gnrc_netdev);
  
  /**
   * @brief Shortcut to set the state of netdev
   *
   * @param[in]   gnrc_netdev    gnrc_netdev structure
   * @param[in]   devstate       new state for netdev
   */
  void _gnrc_lwmac_set_netdev_state(gnrc_netdev_t *gnrc_netdev, netopt_state_t devstate);
  
  /**
   * @brief Convert RTT ticks to device phase
   *
   * @param[in]   ticks    RTT ticks
   *
   * @return               device phase
   */
  static inline uint32_t _gnrc_lwmac_ticks_to_phase(uint32_t ticks)
  {
      assert(GNRC_LWMAC_WAKEUP_INTERVAL_US != 0);
  
      return (ticks % RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US));
  }
  
  /**
   * @brief Get device's current phase
   *
   * @return               device phase
   */
  static inline uint32_t _gnrc_lwmac_phase_now(void)
  {
      return _gnrc_lwmac_ticks_to_phase(rtt_get_counter());
  }
  
  /**
   * @brief Calculate how many ticks remaining to the targeted phase in the future
   *
   * @param[in]   phase    device phase
   *
   * @return               RTT ticks
   */
  static inline uint32_t _gnrc_lwmac_ticks_until_phase(uint32_t phase)
  {
      long int tmp = phase - _gnrc_lwmac_phase_now();
  
      if (tmp < 0) {
          /* Phase in next interval */
          tmp += RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US);
      }
  
      return (uint32_t)tmp;
  }
  
  /**
   * @brief Store the received packet to the dispatch buffer and remove possible
   *        duplicate packets.
   *
   * @param[in,out]   buffer      RX dispatch packet buffer
   * @param[in]       pkt         received packet
   *
   * @return                      0 if correctly stored
   * @return                      <0 on error
   */
  int _gnrc_lwmac_dispatch_defer(gnrc_pktsnip_t * buffer[], gnrc_pktsnip_t * pkt);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* LWMAC_INTERNAL_H */
  /** @} */