mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
395 lines
12 KiB
C
395 lines
12 KiB
C
/*
|
|
* 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/netif.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_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_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_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_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 @ref GNRC_LWMAC_TX_CONTINUE flag of the device
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
* @param[in] tx_continue value for LWMAC tx-continue flag
|
|
*
|
|
*/
|
|
static inline void gnrc_lwmac_set_tx_continue(gnrc_netif_t *netif, bool tx_continue)
|
|
{
|
|
if (tx_continue) {
|
|
netif->mac.mac_info |= GNRC_LWMAC_TX_CONTINUE;
|
|
}
|
|
else {
|
|
netif->mac.mac_info &= ~GNRC_LWMAC_TX_CONTINUE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief get the @ref GNRC_LWMAC_TX_CONTINUE flag of the device
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
*
|
|
* @return true if tx continue
|
|
* @return false if tx will not continue
|
|
*/
|
|
static inline bool gnrc_lwmac_get_tx_continue(gnrc_netif_t *netif)
|
|
{
|
|
return (netif->mac.mac_info & GNRC_LWMAC_TX_CONTINUE);
|
|
}
|
|
|
|
/**
|
|
* @brief set the @ref GNRC_LWMAC_QUIT_TX flag of the device
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
* @param[in] quit_tx value for @ref GNRC_LWMAC_QUIT_TX flag
|
|
*
|
|
*/
|
|
static inline void gnrc_lwmac_set_quit_tx(gnrc_netif_t *netif, bool quit_tx)
|
|
{
|
|
if (quit_tx) {
|
|
netif->mac.mac_info |= GNRC_LWMAC_QUIT_TX;
|
|
}
|
|
else {
|
|
netif->mac.mac_info &= ~GNRC_LWMAC_QUIT_TX;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief get the @ref GNRC_LWMAC_QUIT_TX flag of the device
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
*
|
|
* @return true if quit tx
|
|
* @return false if will not quit tx
|
|
*/
|
|
static inline bool gnrc_lwmac_get_quit_tx(gnrc_netif_t *netif)
|
|
{
|
|
return (netif->mac.mac_info & GNRC_LWMAC_QUIT_TX);
|
|
}
|
|
|
|
/**
|
|
* @brief set the @ref GNRC_LWMAC_PHASE_BACKOFF flag of the device
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
* @param[in] backoff value for LWMAC @ref GNRC_LWMAC_PHASE_BACKOFF flag
|
|
*
|
|
*/
|
|
static inline void gnrc_lwmac_set_phase_backoff(gnrc_netif_t *netif, bool backoff)
|
|
{
|
|
if (backoff) {
|
|
netif->mac.mac_info |= GNRC_LWMAC_PHASE_BACKOFF;
|
|
}
|
|
else {
|
|
netif->mac.mac_info &= ~GNRC_LWMAC_PHASE_BACKOFF;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief get the @ref GNRC_LWMAC_PHASE_BACKOFF flag of the device
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
*
|
|
* @return true if will run phase-backoff
|
|
* @return false if will not run phase-backoff
|
|
*/
|
|
static inline bool gnrc_lwmac_get_phase_backoff(gnrc_netif_t *netif)
|
|
{
|
|
return (netif->mac.mac_info & GNRC_LWMAC_PHASE_BACKOFF);
|
|
}
|
|
|
|
/**
|
|
* @brief set the @ref GNRC_LWMAC_QUIT_RX flag of the device
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
* @param[in] quit_rx value for LWMAC @ref GNRC_LWMAC_QUIT_RX flag
|
|
*
|
|
*/
|
|
static inline void gnrc_lwmac_set_quit_rx(gnrc_netif_t *netif, bool quit_rx)
|
|
{
|
|
if (quit_rx) {
|
|
netif->mac.mac_info |= GNRC_LWMAC_QUIT_RX;
|
|
}
|
|
else {
|
|
netif->mac.mac_info &= ~GNRC_LWMAC_QUIT_RX;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief get the @ref GNRC_LWMAC_QUIT_RX flag of the device
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
*
|
|
* @return true if will quit rx
|
|
* @return false if will not quit rx
|
|
*/
|
|
static inline bool gnrc_lwmac_get_quit_rx(gnrc_netif_t *netif)
|
|
{
|
|
return (netif->mac.mac_info & GNRC_LWMAC_QUIT_RX);
|
|
}
|
|
|
|
/**
|
|
* @brief set the @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag of LWMAC
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
* @param[in] active value for LWMAC @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag
|
|
*
|
|
*/
|
|
static inline void gnrc_lwmac_set_dutycycle_active(gnrc_netif_t *netif, bool active)
|
|
{
|
|
if (active) {
|
|
netif->mac.prot.lwmac.lwmac_info |= GNRC_LWMAC_DUTYCYCLE_ACTIVE;
|
|
}
|
|
else {
|
|
netif->mac.prot.lwmac.lwmac_info &= ~GNRC_LWMAC_DUTYCYCLE_ACTIVE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief get the @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag of LWMAC
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
*
|
|
* @return true if active
|
|
* @return false if not active
|
|
*/
|
|
static inline bool gnrc_lwmac_get_dutycycle_active(gnrc_netif_t *netif)
|
|
{
|
|
return (netif->mac.prot.lwmac.lwmac_info & GNRC_LWMAC_DUTYCYCLE_ACTIVE);
|
|
}
|
|
|
|
/**
|
|
* @brief set the @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag of LWMAC
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
* @param[in] reschedule value for @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag
|
|
*
|
|
*/
|
|
static inline void gnrc_lwmac_set_reschedule(gnrc_netif_t *netif, bool reschedule)
|
|
{
|
|
if (reschedule) {
|
|
netif->mac.prot.lwmac.lwmac_info |= GNRC_LWMAC_NEEDS_RESCHEDULE;
|
|
}
|
|
else {
|
|
netif->mac.prot.lwmac.lwmac_info &= ~GNRC_LWMAC_NEEDS_RESCHEDULE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief get the @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag of LWMAC
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
*
|
|
* @return true if needs rescheduling
|
|
* @return false if no need for rescheduling
|
|
*/
|
|
static inline bool gnrc_lwmac_get_reschedule(gnrc_netif_t *netif)
|
|
{
|
|
return (netif->mac.prot.lwmac.lwmac_info & GNRC_LWMAC_NEEDS_RESCHEDULE);
|
|
}
|
|
|
|
/**
|
|
* @brief send a @ref net_gnrc_pkt "packet" over the network interface in LWMAC
|
|
*
|
|
* @internal
|
|
*
|
|
* @pre `netif != NULL && pkt != NULL`
|
|
*
|
|
* @note The function re-formats the content of @p pkt to a format expected
|
|
* by the netdev_driver_t::send() method of gnrc_netif_t::dev and
|
|
* releases the packet before returning (so no additional release
|
|
* should be required after calling this method).
|
|
*
|
|
* @param[in] netif The network interface.
|
|
* @param[in] pkt A packet to send.
|
|
*
|
|
* @return The number of bytes actually sent on success
|
|
* @return -EBADMSG, if the @ref net_gnrc_netif_hdr in @p pkt is missing
|
|
* or is in an unexpected format.
|
|
* @return -ENOTSUP, if sending @p pkt in the given format isn't supported
|
|
* (e.g. empty payload with Ethernet).
|
|
* @return Any negative error code reported by gnrc_netif_t::dev.
|
|
*/
|
|
int _gnrc_lwmac_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt);
|
|
|
|
/**
|
|
* @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] netif ptr to the network interface
|
|
*
|
|
* @return state of netdev
|
|
*/
|
|
netopt_state_t _gnrc_lwmac_get_netdev_state(gnrc_netif_t *netif);
|
|
|
|
/**
|
|
* @brief Shortcut to set the state of netdev
|
|
*
|
|
* @param[in] netif ptr to the network interface
|
|
* @param[in] devstate new state for netdev
|
|
*/
|
|
void _gnrc_lwmac_set_netdev_state(gnrc_netif_t *netif, 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(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US != 0);
|
|
|
|
return (ticks % RTT_US_TO_TICKS(CONFIG_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(CONFIG_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 */
|
|
/** @} */
|