1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #7895 from zhuoshuguo/lwmac_port_to_netif2

gnrc_lwmac: port to gnrc_netif2
This commit is contained in:
Martine Lenders 2017-11-01 16:10:56 +01:00 committed by GitHub
commit ea27fe34d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1149 additions and 915 deletions

View File

@ -559,8 +559,8 @@ ifneq (,$(filter netstats_%, $(USEMODULE)))
endif
ifneq (,$(filter gnrc_lwmac,$(USEMODULE)))
USEMODULE += gnrc_netif2
USEMODULE += gnrc_mac
USEMODULE += gnrc_netdev
FEATURES_REQUIRED += periph_rtt
endif

View File

@ -61,10 +61,17 @@ void auto_init_at86rf2xx(void)
at86rf2xx_setup(&at86rf2xx_devs[i], &at86rf2xx_params[i]);
#ifdef MODULE_GNRC_NETIF2
#ifdef MODULE_GNRC_LWMAC
gnrc_netif2_lwmac_create(_at86rf2xx_stacks[i],
AT86RF2XX_MAC_STACKSIZE,
AT86RF2XX_MAC_PRIO, "at86rf2xx-lwmac",
(netdev_t *)&at86rf2xx_devs[i]);
#else
gnrc_netif2_ieee802154_create(_at86rf2xx_stacks[i],
AT86RF2XX_MAC_STACKSIZE,
AT86RF2XX_MAC_PRIO, "at86rf2xx",
(netdev_t *)&at86rf2xx_devs[i]);
#endif
#else
int res = gnrc_netdev_ieee802154_init(&gnrc_adpt[i],
(netdev_ieee802154_t *)&at86rf2xx_devs[i]);
@ -73,19 +80,11 @@ void auto_init_at86rf2xx(void)
LOG_ERROR("[auto_init_netif] error initializing at86rf2xx radio #%u\n", i);
}
else {
#ifdef MODULE_GNRC_LWMAC
gnrc_lwmac_init(_at86rf2xx_stacks[i],
AT86RF2XX_MAC_STACKSIZE,
AT86RF2XX_MAC_PRIO,
"at86rf2xx-lwmac",
&gnrc_adpt[i]);
#else
gnrc_netdev_init(_at86rf2xx_stacks[i],
AT86RF2XX_MAC_STACKSIZE,
AT86RF2XX_MAC_PRIO,
"at86rf2xx",
&gnrc_adpt[i]);
#endif
}
#endif
}

View File

@ -59,8 +59,8 @@ extern "C" {
* @brief LWMAC internal L2 address structure
*/
typedef struct {
uint8_t addr[IEEE802154_LONG_ADDRESS_LEN]; /**< address of node */
uint8_t len; /**< address */
uint8_t addr[IEEE802154_LONG_ADDRESS_LEN]; /**< address of node */
uint8_t len; /**< address */
} gnrc_lwmac_l2_addr_t;
/**
@ -79,25 +79,25 @@ typedef struct {
* @brief LWMAC WR (wake-up request packet, i.e., preamble packet) frame
*/
typedef struct __attribute__((packed)) {
gnrc_lwmac_hdr_t header; /**< WR packet header type */
gnrc_lwmac_l2_addr_t dst_addr; /**< WR is broadcast, so destination address needed */
gnrc_lwmac_hdr_t header; /**< WR packet header type */
gnrc_lwmac_l2_addr_t dst_addr; /**< WR is broadcast, so destination address needed */
} gnrc_lwmac_frame_wr_t;
/**
* @brief LWMAC WA (wake-up answer packet, i.e., preamble-ACK packet) frame
*/
typedef struct __attribute__((packed)) {
gnrc_lwmac_hdr_t header; /**< WA packet header type */
gnrc_lwmac_l2_addr_t dst_addr; /**< WA is broadcast, so destination address needed */
uint32_t current_phase; /**< Node's current phase value */
gnrc_lwmac_hdr_t header; /**< WA packet header type */
gnrc_lwmac_l2_addr_t dst_addr; /**< WA is broadcast, so destination address needed */
uint32_t current_phase; /**< Node's current phase value */
} gnrc_lwmac_frame_wa_t;
/**
* @brief LWMAC broadcast data frame
*/
typedef struct __attribute__((packed)) {
gnrc_lwmac_hdr_t header; /**< Broadcast packet header type */
uint8_t seq_nr; /**< Broadcast sequence */
gnrc_lwmac_hdr_t header; /**< Broadcast packet header type */
uint8_t seq_nr; /**< Broadcast sequence */
} gnrc_lwmac_frame_broadcast_t;
/**

View File

@ -74,7 +74,7 @@
#define NET_GNRC_LWMAC_LWMAC_H
#include "kernel_types.h"
#include "net/gnrc/netdev.h"
#include "net/gnrc/netif2.h"
#ifdef __cplusplus
extern "C" {
@ -95,7 +95,7 @@ extern "C" {
* In LWMAC, by default, we regard the wake-up period as the beginning of a cycle.
*/
#ifndef GNRC_LWMAC_WAKEUP_INTERVAL_US
#define GNRC_LWMAC_WAKEUP_INTERVAL_US (100LU * US_PER_MS)
#define GNRC_LWMAC_WAKEUP_INTERVAL_US (200LU *US_PER_MS)
#endif
/**
@ -110,7 +110,7 @@ extern "C" {
* @ref GNRC_LWMAC_WAKEUP_INTERVAL_US.
*/
#ifndef GNRC_LWMAC_PREAMBLE_DURATION_US
#define GNRC_LWMAC_PREAMBLE_DURATION_US ((13LU * GNRC_LWMAC_WAKEUP_INTERVAL_US) / 10)
#define GNRC_LWMAC_PREAMBLE_DURATION_US ((13LU *GNRC_LWMAC_WAKEUP_INTERVAL_US) / 10)
#endif
/**
@ -129,7 +129,7 @@ extern "C" {
* send a WR with the given hardware (including processor) and data rate.
*/
#ifndef GNRC_LWMAC_TIME_BETWEEN_WR_US
#define GNRC_LWMAC_TIME_BETWEEN_WR_US (5U * US_PER_MS)
#define GNRC_LWMAC_TIME_BETWEEN_WR_US (5U *US_PER_MS)
#endif
/**
@ -187,7 +187,7 @@ extern "C" {
* period of the receiver, otherwise will lead to a long WR procedure.
*/
#ifndef GNRC_LWMAC_WR_PREPARATION_US
#define GNRC_LWMAC_WR_PREPARATION_US ((3U * US_PER_MS))
#define GNRC_LWMAC_WR_PREPARATION_US ((3U *US_PER_MS))
#endif
/**
@ -207,7 +207,7 @@ extern "C" {
* supports @ref NETDEV_EVENT_RX_STARTED event (this can be important for big packets).
*/
#ifndef GNRC_LWMAC_DATA_DELAY_US
#define GNRC_LWMAC_DATA_DELAY_US (10U * US_PER_MS)
#define GNRC_LWMAC_DATA_DELAY_US (10U *US_PER_MS)
#endif
/**
@ -298,24 +298,22 @@ extern "C" {
#endif
/**
* @brief Initialize an instance of the LWMAC layer
* @brief Creates an IEEE 802.15.4 LWMAC network interface
*
* The initialization starts a new thread that connects to the given netdev
* device and starts a link layer event loop.
* @param[in] stack The stack for the LWMAC network interface's thread.
* @param[in] stacksize Size of @p stack.
* @param[in] priority Priority for the LWMAC network interface's thread.
* @param[in] name Name for the LWMAC network interface. May be NULL.
* @param[in] dev Device for the interface
*
* @param[in] stack stack for the control thread
* @param[in] stacksize size of *stack*
* @param[in] priority priority for the thread housing the LWMAC instance
* @param[in] name name of the thread housing the LWMAC instance
* @param[in] dev netdev device, needs to be already initialized
* @see @ref gnrc_netif2_create()
*
* @return PID of LWMAC thread on success
* @return -EINVAL if creation of thread fails
* @return -ENODEV if *dev* is invalid
* @return The network interface on success.
* @return NULL, on error.
*/
kernel_pid_t gnrc_lwmac_init(char *stack, int stacksize, char priority,
const char *name, gnrc_netdev_t *dev);
gnrc_netif2_t *gnrc_netif2_lwmac_create(char *stack, int stacksize,
char priority, char *name,
netdev_t *dev);
#ifdef __cplusplus
}
#endif

View File

@ -25,7 +25,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "net/gnrc/netdev.h"
#include "net/gnrc/netif2.h"
#include "net/gnrc/lwmac/types.h"
#ifdef __cplusplus
@ -40,52 +40,52 @@ extern "C" {
/**
* @brief Set LWMAC timeout of type @p type of offset @p offset.
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif the network interface
* @param[in] type LWMAC timeout type
* @param[in] offset timeout offset
*/
void gnrc_lwmac_set_timeout(gnrc_netdev_t *gnrc_netdev,
void gnrc_lwmac_set_timeout(gnrc_netif2_t *netif,
gnrc_lwmac_timeout_type_t type,
uint32_t offset);
/**
* @brief Clear LWMAC timeout of type @p type.
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif the network interface
* @param[in] type LWMAC timeout type
*/
void gnrc_lwmac_clear_timeout(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_timeout_type_t type);
void gnrc_lwmac_clear_timeout(gnrc_netif2_t *netif, gnrc_lwmac_timeout_type_t type);
/**
* @brief Check whether LWMAC timeout of type @p type is running.
*
* @param[in] gnrc_netdev gnrc_netdev structure
* @param[in] netif the network interface
* @param[in] type LWMAC timeout type
*
* @return true, if timeout of type @p type is running.
* @return false, if timeout of type @p type is not running.
*/
bool gnrc_lwmac_timeout_is_running(gnrc_netdev_t *gnrc_netdev,
bool gnrc_lwmac_timeout_is_running(gnrc_netif2_t *netif,
gnrc_lwmac_timeout_type_t type);
/**
* @brief Check whether LWMAC timeout of type @p type is expired. It will clear
* the timeout once it is found expired.
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif the network interface
* @param[in] type LWMAC timeout type
*
* @return true, if timeout of type @p type is expired.
* @return false, if timeout of type @p type is not expired, or not exist.
*/
bool gnrc_lwmac_timeout_is_expired(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_timeout_type_t type);
bool gnrc_lwmac_timeout_is_expired(gnrc_netif2_t *netif, gnrc_lwmac_timeout_type_t type);
/**
* @brief Reset all LWMAC timeouts.
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif the network interface
*/
void gnrc_lwmac_reset_timeouts(gnrc_netdev_t *gnrc_netdev);
void gnrc_lwmac_reset_timeouts(gnrc_netif2_t *netif);
/**
* @brief Make a specific LWMAC timeout expired.

View File

@ -109,32 +109,32 @@ extern "C" {
* @brief Internal states of LWMAC
*/
typedef enum {
GNRC_LWMAC_UNDEF = -1, /**< Undefined state of LWMAC */
GNRC_LWMAC_STOPPED, /**< LWMAC's main state machine has been stopped */
GNRC_LWMAC_START, /**< Start LWMAC's main state machine */
GNRC_LWMAC_STOP, /**< Stop LWMAC's main state machine */
GNRC_LWMAC_RESET, /**< Reset LWMAC's main state machine */
GNRC_LWMAC_LISTENING, /**< Listen the channel for receiving packets */
GNRC_LWMAC_RECEIVING, /**< RX is handled in own state machine */
GNRC_LWMAC_TRANSMITTING, /**< TX is handled in own state machine */
GNRC_LWMAC_SLEEPING, /**< Turn off radio to conserve power */
GNRC_LWMAC_STATE_COUNT /**< Count of LWMAC's states */
GNRC_LWMAC_UNDEF = -1, /**< Undefined state of LWMAC */
GNRC_LWMAC_STOPPED, /**< LWMAC's main state machine has been stopped */
GNRC_LWMAC_START, /**< Start LWMAC's main state machine */
GNRC_LWMAC_STOP, /**< Stop LWMAC's main state machine */
GNRC_LWMAC_RESET, /**< Reset LWMAC's main state machine */
GNRC_LWMAC_LISTENING, /**< Listen the channel for receiving packets */
GNRC_LWMAC_RECEIVING, /**< RX is handled in own state machine */
GNRC_LWMAC_TRANSMITTING, /**< TX is handled in own state machine */
GNRC_LWMAC_SLEEPING, /**< Turn off radio to conserve power */
GNRC_LWMAC_STATE_COUNT /**< Count of LWMAC's states */
} gnrc_lwmac_state_t;
/**
* @brief TX states of LWMAC
*/
typedef enum {
GNRC_LWMAC_TX_STATE_STOPPED, /**< Tx schedule stopped, stop sending packet */
GNRC_LWMAC_TX_STATE_INIT, /**< Initiate transmission */
GNRC_LWMAC_TX_STATE_SEND_BROADCAST, /**< directly goes to SUCCESSFUL or FAILED when finished */
GNRC_LWMAC_TX_STATE_SEND_WR, /**< Send a wakeup request */
GNRC_LWMAC_TX_STATE_WAIT_WR_SENT, /**< Wait until WR sent to set timeout */
GNRC_LWMAC_TX_STATE_WAIT_FOR_WA, /**< Wait for dest node's wakeup ackknowledge */
GNRC_LWMAC_TX_STATE_SEND_DATA, /**< Send the actual payload data */
GNRC_LWMAC_TX_STATE_WAIT_FEEDBACK, /**< Wait if packet was ACKed */
GNRC_LWMAC_TX_STATE_SUCCESSFUL, /**< Transmission has finished successfully */
GNRC_LWMAC_TX_STATE_FAILED /**< Payload data couldn't be delivered to dest */
GNRC_LWMAC_TX_STATE_STOPPED, /**< Tx schedule stopped, stop sending packet */
GNRC_LWMAC_TX_STATE_INIT, /**< Initiate transmission */
GNRC_LWMAC_TX_STATE_SEND_BROADCAST, /**< directly goes to SUCCESSFUL or FAILED when finished */
GNRC_LWMAC_TX_STATE_SEND_WR, /**< Send a wakeup request */
GNRC_LWMAC_TX_STATE_WAIT_WR_SENT, /**< Wait until WR sent to set timeout */
GNRC_LWMAC_TX_STATE_WAIT_FOR_WA, /**< Wait for dest node's wakeup ackknowledge */
GNRC_LWMAC_TX_STATE_SEND_DATA, /**< Send the actual payload data */
GNRC_LWMAC_TX_STATE_WAIT_FEEDBACK, /**< Wait if packet was ACKed */
GNRC_LWMAC_TX_STATE_SUCCESSFUL, /**< Transmission has finished successfully */
GNRC_LWMAC_TX_STATE_FAILED /**< Payload data couldn't be delivered to dest */
} gnrc_lwmac_tx_state_t;
/**
@ -146,14 +146,14 @@ typedef enum {
* @brief RX states of LWMAC
*/
typedef enum {
GNRC_LWMAC_RX_STATE_STOPPED, /**< Rx schedule stopped */
GNRC_LWMAC_RX_STATE_INIT, /**< Initiate reception */
GNRC_LWMAC_RX_STATE_WAIT_FOR_WR, /**< Wait for a wakeup request */
GNRC_LWMAC_RX_STATE_SEND_WA, /**< Send wakeup ackknowledge to requesting node */
GNRC_LWMAC_RX_STATE_WAIT_WA_SENT, /**< Wait until WA sent to set timeout */
GNRC_LWMAC_RX_STATE_WAIT_FOR_DATA, /**< Wait for actual payload data */
GNRC_LWMAC_RX_STATE_SUCCESSFUL, /**< Recption has finished successfully */
GNRC_LWMAC_RX_STATE_FAILED /**< Reception over, but nothing received */
GNRC_LWMAC_RX_STATE_STOPPED, /**< Rx schedule stopped */
GNRC_LWMAC_RX_STATE_INIT, /**< Initiate reception */
GNRC_LWMAC_RX_STATE_WAIT_FOR_WR, /**< Wait for a wakeup request */
GNRC_LWMAC_RX_STATE_SEND_WA, /**< Send wakeup ackknowledge to requesting node */
GNRC_LWMAC_RX_STATE_WAIT_WA_SENT, /**< Wait until WA sent to set timeout */
GNRC_LWMAC_RX_STATE_WAIT_FOR_DATA, /**< Wait for actual payload data */
GNRC_LWMAC_RX_STATE_SUCCESSFUL, /**< Recption has finished successfully */
GNRC_LWMAC_RX_STATE_FAILED /**< Reception over, but nothing received */
} gnrc_lwmac_rx_state_t;
/**
@ -175,14 +175,14 @@ typedef enum {
* @brief LWMAC timeout types
*/
typedef enum {
GNRC_LWMAC_TIMEOUT_DISABLED, /**< Timeout is diabled */
GNRC_LWMAC_TIMEOUT_WR, /**< WR timeout, waiting WA */
GNRC_LWMAC_TIMEOUT_NO_RESPONSE, /**< Maximum WR duration timeout awaiting WA */
GNRC_LWMAC_TIMEOUT_DATA, /**< Timeout awaiting data packet from receiver */
GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP, /**< Timeout for waiting receiver's wake-up phase */
GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD, /**< Wake up period timeout for going to sleep */
GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST, /**< Timeout for waiting to send the next broadcast packet */
GNRC_LWMAC_TIMEOUT_BROADCAST_END, /**< Timeout awaiting the end of the whole broadcast period */
GNRC_LWMAC_TIMEOUT_DISABLED, /**< Timeout is diabled */
GNRC_LWMAC_TIMEOUT_WR, /**< WR timeout, waiting WA */
GNRC_LWMAC_TIMEOUT_NO_RESPONSE, /**< Maximum WR duration timeout awaiting WA */
GNRC_LWMAC_TIMEOUT_DATA, /**< Timeout awaiting data packet from receiver */
GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP, /**< Timeout for waiting receiver's wake-up phase */
GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD, /**< Wake up period timeout for going to sleep */
GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST, /**< Timeout for waiting to send the next broadcast packet */
GNRC_LWMAC_TIMEOUT_BROADCAST_END, /**< Timeout awaiting the end of the whole broadcast period */
} gnrc_lwmac_timeout_type_t;
/**
@ -199,19 +199,19 @@ typedef struct {
* @brief LWMAC specific structure for storing internal states.
*/
typedef struct lwmac {
gnrc_lwmac_state_t state; /**< Internal state of MAC layer */
uint32_t last_wakeup; /**< Used to calculate wakeup times */
uint8_t lwmac_info; /**< LWMAC's internal informations (flags) */
gnrc_lwmac_timeout_t timeouts[GNRC_LWMAC_TIMEOUT_COUNT]; /**< Store timeouts used for protocol */
gnrc_lwmac_state_t state; /**< Internal state of MAC layer */
uint32_t last_wakeup; /**< Used to calculate wakeup times */
uint8_t lwmac_info; /**< LWMAC's internal informations (flags) */
gnrc_lwmac_timeout_t timeouts[GNRC_LWMAC_TIMEOUT_COUNT]; /**< Store timeouts used for protocol */
#if (GNRC_LWMAC_ENABLE_DUTYCYLE_RECORD == 1)
/* Parameters for recording duty-cycle */
uint32_t last_radio_on_time_ticks; /**< The last time in ticks when radio is on */
uint32_t radio_off_time_ticks; /**< The time in ticks when radio is off */
uint32_t system_start_time_ticks; /**< The time in ticks when chip is started */
uint32_t awake_duration_sum_ticks; /**< The sum of time in ticks when radio is on */
uint32_t pkt_start_sending_time_ticks; /**< The time in ticks when the packet is started
to be sent */
uint32_t last_radio_on_time_ticks; /**< The last time in ticks when radio is on */
uint32_t radio_off_time_ticks; /**< The time in ticks when radio is off */
uint32_t system_start_time_ticks; /**< The time in ticks when chip is started */
uint32_t awake_duration_sum_ticks; /**< The sum of time in ticks when radio is on */
uint32_t pkt_start_sending_time_ticks; /**< The time in ticks when the packet is started
to be sent */
#endif
} gnrc_lwmac_t;

View File

@ -25,11 +25,76 @@
#include "net/ieee802154.h"
#include "net/gnrc/mac/types.h"
#include "net/gnrc/netif2.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief get the 'rx_started' state of the device
*
* This function checks whether the device has started receiving a packet.
*
* @param[in] netif the network interface
*
* @return the rx_started state
*/
static inline bool gnrc_netif2_get_rx_started(gnrc_netif2_t *netif)
{
return (netif->mac.mac_info & GNRC_NETIF2_MAC_INFO_RX_STARTED);
}
/**
* @brief set the rx_started state of the device
*
* This function is intended to be called only in netdev_t::event_callback().
*
* @param[in] netif the network interface
* @param[in] rx_started the rx_started state
*/
static inline void gnrc_netif2_set_rx_started(gnrc_netif2_t *netif, bool rx_started)
{
if (rx_started) {
netif->mac.mac_info |= GNRC_NETIF2_MAC_INFO_RX_STARTED;
}
else {
netif->mac.mac_info &= ~GNRC_NETIF2_MAC_INFO_RX_STARTED;
}
}
/**
* @brief get the transmission feedback of the device
*
* @param[in] netif the network interface
*
* @return the transmission feedback
*/
static inline gnrc_mac_tx_feedback_t gnrc_netif2_get_tx_feedback(gnrc_netif2_t *netif)
{
return (gnrc_mac_tx_feedback_t)(netif->mac.mac_info &
GNRC_NETIF2_MAC_INFO_TX_FEEDBACK_MASK);
}
/**
* @brief set the transmission feedback of the device
*
* This function is intended to be called only in netdev_t::event_callback().
*
* @param[in] netif the network interface
* @param[in] txf the transmission feedback
*/
static inline void gnrc_netif2_set_tx_feedback(gnrc_netif2_t *netif,
gnrc_mac_tx_feedback_t txf)
{
/* check if gnrc_mac_tx_feedback does not collide with
* GNRC_NETIF2_MAC_INFO_RX_STARTED */
assert(!(txf & GNRC_NETIF2_MAC_INFO_RX_STARTED));
/* unset previous value */
netif->mac.mac_info &= ~GNRC_NETIF2_MAC_INFO_TX_FEEDBACK_MASK;
netif->mac.mac_info |= (uint16_t)(txf & GNRC_NETIF2_MAC_INFO_TX_FEEDBACK_MASK);
}
#if (GNRC_MAC_TX_QUEUE_SIZE != 0) || defined(DOXYGEN)
/**
* @brief Queues the packet into the related transmission packet queue in netdev_t::tx.

View File

@ -19,15 +19,46 @@
#define NET_GNRC_NETIF2_MAC_H
#include "net/gnrc/mac/types.h"
#include "net/csma_sender.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Mask for @ref gnrc_mac_tx_feedback_t
*/
#define GNRC_NETIF2_MAC_INFO_TX_FEEDBACK_MASK (0x0003U)
/**
* @brief Flag to track if a transmission might have corrupted a received
* packet
*/
#define GNRC_NETIF2_MAC_INFO_RX_STARTED (0x0004U)
/**
* @brief Flag to track if a device has enabled CSMA for transmissions
*
* In case the device doesn't support on-chip CSMA and this flag is set for
* requiring CSMA transmission, then, the device will run software CSMA
* using `csma_sender` APIs.
*/
#define GNRC_NETIF2_MAC_INFO_CSMA_ENABLED (0x0100U)
/**
* @brief @ref net_gnrc_mac component of @ref gnrc_netif2_mac_t
*/
typedef struct {
/**
* @brief general information for the MAC protocol
*/
uint16_t mac_info;
/**
* @brief device's software CSMA configuration
*/
csma_sender_conf_t csma_conf;
#if ((GNRC_MAC_RX_QUEUE_SIZE != 0) || (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0)) || DOXYGEN
/**
* @brief MAC internal object which stores reception parameters, queues, and
@ -48,6 +79,13 @@ typedef struct {
*/
gnrc_mac_tx_t tx;
#endif /* ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (GNRC_MAC_NEIGHBOR_COUNT == 0)) || DOXYGEN */
#ifdef MODULE_GNRC_LWMAC
/**
* @brief LWMAC specific structure object for storing LWMAC internal states.
*/
gnrc_lwmac_t lwmac;
#endif
} gnrc_netif2_mac_t;
#ifdef __cplusplus

View File

@ -24,7 +24,7 @@
#include <stdint.h>
#include "periph/rtt.h"
#include "net/gnrc/netdev.h"
#include "net/gnrc/netif2.h"
#include "net/gnrc/mac/types.h"
#include "net/gnrc/lwmac/types.h"
@ -41,7 +41,7 @@ extern "C" {
* 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)
#define GNRC_LWMAC_TX_CONTINUE (0x0008U)
/**
* @brief Flag to track if the sender should quit Tx in current cycle.
@ -53,7 +53,7 @@ extern "C" {
* cycle (started by the wake-up period), thus not to collide with other
* (neighbor) nodes' transmissions.
*/
#define GNRC_NETDEV_LWMAC_QUIT_TX (0x0010U)
#define GNRC_LWMAC_QUIT_TX (0x0010U)
/**
* @brief Flag to track if the device need to reselect a new wake-up phase.
@ -65,7 +65,7 @@ extern "C" {
* 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)
#define GNRC_LWMAC_PHASE_BACKOFF (0x0020U)
/**
* @brief Flag to track if the device needs to quit the wake-up (listening) procedure.
@ -78,15 +78,15 @@ extern "C" {
* 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)
#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_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;
/**
@ -98,185 +98,209 @@ typedef struct {
#define GNRC_LWMAC_RTT_EVENT_MARGIN_TICKS (RTT_MS_TO_TICKS(2))
/**
* @brief set the TX-continue flag of the device
* @brief set the @ref GNRC_LWMAC_TX_CONTINUE flag of the device
*
* @param[in] dev ptr to netdev device
* @param[in] netif ptr to the network interface
* @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)
static inline void gnrc_lwmac_set_tx_continue(gnrc_netif2_t *netif, bool tx_continue)
{
if (tx_continue) {
dev->mac_info |= GNRC_NETDEV_LWMAC_TX_CONTINUE;
netif->mac.mac_info |= GNRC_LWMAC_TX_CONTINUE;
}
else {
dev->mac_info &= ~GNRC_NETDEV_LWMAC_TX_CONTINUE;
netif->mac.mac_info &= ~GNRC_LWMAC_TX_CONTINUE;
}
}
/**
* @brief get the TX-continue flag of the device
* @brief get the @ref GNRC_LWMAC_TX_CONTINUE flag of the device
*
* @param[in] dev ptr to netdev device
* @param[in] netif ptr to the network interface
*
* @return true if tx continue
* @return false if tx will continue
* @return false if tx will not continue
*/
static inline bool gnrc_netdev_lwmac_get_tx_continue(gnrc_netdev_t *dev)
static inline bool gnrc_lwmac_get_tx_continue(gnrc_netif2_t *netif)
{
return (dev->mac_info & GNRC_NETDEV_LWMAC_TX_CONTINUE);
return (netif->mac.mac_info & GNRC_LWMAC_TX_CONTINUE);
}
/**
* @brief set the quit-TX flag of the device
* @brief set the @ref GNRC_LWMAC_QUIT_TX flag of the device
*
* @param[in] dev ptr to netdev device
* @param[in] quit_tx value for LWMAC quit-TX flag
* @param[in] netif ptr to the network interface
* @param[in] quit_tx value for @ref GNRC_LWMAC_QUIT_TX flag
*
*/
static inline void gnrc_netdev_lwmac_set_quit_tx(gnrc_netdev_t *dev, bool quit_tx)
static inline void gnrc_lwmac_set_quit_tx(gnrc_netif2_t *netif, bool quit_tx)
{
if (quit_tx) {
dev->mac_info |= GNRC_NETDEV_LWMAC_QUIT_TX;
netif->mac.mac_info |= GNRC_LWMAC_QUIT_TX;
}
else {
dev->mac_info &= ~GNRC_NETDEV_LWMAC_QUIT_TX;
netif->mac.mac_info &= ~GNRC_LWMAC_QUIT_TX;
}
}
/**
* @brief get the quit-TX flag of the device
* @brief get the @ref GNRC_LWMAC_QUIT_TX flag of the device
*
* @param[in] dev ptr to netdev 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_netdev_lwmac_get_quit_tx(gnrc_netdev_t *dev)
static inline bool gnrc_lwmac_get_quit_tx(gnrc_netif2_t *netif)
{
return (dev->mac_info & GNRC_NETDEV_LWMAC_QUIT_TX);
return (netif->mac.mac_info & GNRC_LWMAC_QUIT_TX);
}
/**
* @brief set the phase-backoff flag of the device
* @brief set the @ref GNRC_LWMAC_PHASE_BACKOFF flag of the device
*
* @param[in] dev ptr to netdev device
* @param[in] backoff value for LWMAC phase-backoff flag
* @param[in] netif ptr to the network interface
* @param[in] backoff value for LWMAC @ref GNRC_LWMAC_PHASE_BACKOFF flag
*
*/
static inline void gnrc_netdev_lwmac_set_phase_backoff(gnrc_netdev_t *dev, bool backoff)
static inline void gnrc_lwmac_set_phase_backoff(gnrc_netif2_t *netif, bool backoff)
{
if (backoff) {
dev->mac_info |= GNRC_NETDEV_LWMAC_PHASE_BACKOFF;
netif->mac.mac_info |= GNRC_LWMAC_PHASE_BACKOFF;
}
else {
dev->mac_info &= ~GNRC_NETDEV_LWMAC_PHASE_BACKOFF;
netif->mac.mac_info &= ~GNRC_LWMAC_PHASE_BACKOFF;
}
}
/**
* @brief get the phase-backoff of the device
* @brief get the @ref GNRC_LWMAC_PHASE_BACKOFF flag of the device
*
* @param[in] dev ptr to netdev 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_netdev_lwmac_get_phase_backoff(gnrc_netdev_t *dev)
static inline bool gnrc_lwmac_get_phase_backoff(gnrc_netif2_t *netif)
{
return (dev->mac_info & GNRC_NETDEV_LWMAC_PHASE_BACKOFF);
return (netif->mac.mac_info & GNRC_LWMAC_PHASE_BACKOFF);
}
/**
* @brief set the quit-RX flag of the device
* @brief set the @ref GNRC_LWMAC_QUIT_RX flag of the device
*
* @param[in] dev ptr to netdev device
* @param[in] quit_rx value for LWMAC quit-Rx flag
* @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_netdev_lwmac_set_quit_rx(gnrc_netdev_t *dev, bool quit_rx)
static inline void gnrc_lwmac_set_quit_rx(gnrc_netif2_t *netif, bool quit_rx)
{
if (quit_rx) {
dev->mac_info |= GNRC_NETDEV_LWMAC_QUIT_RX;
netif->mac.mac_info |= GNRC_LWMAC_QUIT_RX;
}
else {
dev->mac_info &= ~GNRC_NETDEV_LWMAC_QUIT_RX;
netif->mac.mac_info &= ~GNRC_LWMAC_QUIT_RX;
}
}
/**
* @brief get the quit-RX flag of the device
* @brief get the @ref GNRC_LWMAC_QUIT_RX flag of the device
*
* @param[in] dev ptr to netdev 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_netdev_lwmac_get_quit_rx(gnrc_netdev_t *dev)
static inline bool gnrc_lwmac_get_quit_rx(gnrc_netif2_t *netif)
{
return (dev->mac_info & GNRC_NETDEV_LWMAC_QUIT_RX);
return (netif->mac.mac_info & GNRC_LWMAC_QUIT_RX);
}
/**
* @brief set the duty-cycle-active flag of LWMAC
* @brief set the @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag of LWMAC
*
* @param[in] dev ptr to netdev device
* @param[in] active value for LWMAC duty-cycle-active flag
* @param[in] netif ptr to the network interface
* @param[in] active value for LWMAC @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag
*
*/
static inline void gnrc_netdev_lwmac_set_dutycycle_active(gnrc_netdev_t *dev, bool active)
static inline void gnrc_lwmac_set_dutycycle_active(gnrc_netif2_t *netif, bool active)
{
if (active) {
dev->lwmac.lwmac_info |= GNRC_LWMAC_DUTYCYCLE_ACTIVE;
netif->mac.lwmac.lwmac_info |= GNRC_LWMAC_DUTYCYCLE_ACTIVE;
}
else {
dev->lwmac.lwmac_info &= ~GNRC_LWMAC_DUTYCYCLE_ACTIVE;
netif->mac.lwmac.lwmac_info &= ~GNRC_LWMAC_DUTYCYCLE_ACTIVE;
}
}
/**
* @brief get the duty-cycle-active flag of LWMAC
* @brief get the @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag of LWMAC
*
* @param[in] dev ptr to netdev device
* @param[in] netif ptr to the network interface
*
* @return true if active
* @return false if not active
*/
static inline bool gnrc_netdev_lwmac_get_dutycycle_active(gnrc_netdev_t *dev)
static inline bool gnrc_lwmac_get_dutycycle_active(gnrc_netif2_t *netif)
{
return (dev->lwmac.lwmac_info & GNRC_LWMAC_DUTYCYCLE_ACTIVE);
return (netif->mac.lwmac.lwmac_info & GNRC_LWMAC_DUTYCYCLE_ACTIVE);
}
/**
* @brief set the needs-rescheduling flag of LWMAC
* @brief set the @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag of LWMAC
*
* @param[in] dev ptr to netdev device
* @param[in] reschedule value for LWMAC needs-rescheduling flag
* @param[in] netif ptr to the network interface
* @param[in] reschedule value for @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag
*
*/
static inline void gnrc_netdev_lwmac_set_reschedule(gnrc_netdev_t *dev, bool reschedule)
static inline void gnrc_lwmac_set_reschedule(gnrc_netif2_t *netif, bool reschedule)
{
if (reschedule) {
dev->lwmac.lwmac_info |= GNRC_LWMAC_NEEDS_RESCHEDULE;
netif->mac.lwmac.lwmac_info |= GNRC_LWMAC_NEEDS_RESCHEDULE;
}
else {
dev->lwmac.lwmac_info &= ~GNRC_LWMAC_NEEDS_RESCHEDULE;
netif->mac.lwmac.lwmac_info &= ~GNRC_LWMAC_NEEDS_RESCHEDULE;
}
}
/**
* @brief get the needs-rescheduling flag of LWMAC
* @brief get the @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag of LWMAC
*
* @param[in] dev ptr to netdev device
* @param[in] netif ptr to the network interface
*
* @return true if needs rescheduling
* @return false if no need for rescheduling
*/
static inline bool gnrc_netdev_lwmac_get_reschedule(gnrc_netdev_t *dev)
static inline bool gnrc_lwmac_get_reschedule(gnrc_netif2_t *netif)
{
return (dev->lwmac.lwmac_info & GNRC_LWMAC_NEEDS_RESCHEDULE);
return (netif->mac.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_netif2_t::dev.
*/
int _gnrc_lwmac_transmit(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt);
/**
* @brief Parse an incoming packet and extract important information.
*
@ -293,19 +317,19 @@ 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
* @param[in] netif ptr to the network interface
*
* @return state of netdev
* @return state of netdev
*/
netopt_state_t _gnrc_lwmac_get_netdev_state(gnrc_netdev_t *gnrc_netdev);
netopt_state_t _gnrc_lwmac_get_netdev_state(gnrc_netif2_t *netif);
/**
* @brief Shortcut to set the state of netdev
*
* @param[in] gnrc_netdev gnrc_netdev structure
* @param[in] devstate new state for netdev
* @param[in] netif ptr to the network interface
* @param[in] devstate new state for netdev
*/
void _gnrc_lwmac_set_netdev_state(gnrc_netdev_t *gnrc_netdev, netopt_state_t devstate);
void _gnrc_lwmac_set_netdev_state(gnrc_netif2_t *netif, netopt_state_t devstate);
/**
* @brief Convert RTT ticks to device phase

View File

@ -23,7 +23,7 @@
#define RX_STATE_MACHINE_H
#include "net/gnrc/pkt.h"
#include "net/gnrc/netdev.h"
#include "net/gnrc/netif2.h"
#ifdef __cplusplus
extern "C" {
@ -32,26 +32,26 @@ extern "C" {
/**
* @brief Start LWMAC RX procedure to receive packet
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif ptr to the network interface
*
*/
void gnrc_lwmac_rx_start(gnrc_netdev_t *gnrc_netdev);
void gnrc_lwmac_rx_start(gnrc_netif2_t *netif);
/**
* @brief Stop LWMAC RX procedure
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif ptr to the network interface
*
*/
void gnrc_lwmac_rx_stop(gnrc_netdev_t *gnrc_netdev);
void gnrc_lwmac_rx_stop(gnrc_netif2_t *netif);
/**
* @brief Update LWMAC RX procedure for packet reception
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif ptr to the network interface
*
*/
void gnrc_lwmac_rx_update(gnrc_netdev_t *gnrc_netdev);
void gnrc_lwmac_rx_update(gnrc_netif2_t *netif);
#ifdef __cplusplus
}

View File

@ -23,7 +23,7 @@
#define TX_STATE_MACHINE_H
#include "net/gnrc/pkt.h"
#include "net/gnrc/netdev.h"
#include "net/gnrc/netif2.h"
#include "net/gnrc/mac/types.h"
#ifdef __cplusplus
@ -33,30 +33,30 @@ extern "C" {
/**
* @brief Start LWMAC TX procedure to transmit packet @p pkt to @p neighbor
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif ptr to the network interface
* @param[in] pkt packet to transmit
* @param[in] neighbor Tx neighbor
*
*/
void gnrc_lwmac_tx_start(gnrc_netdev_t *gnrc_netdev,
void gnrc_lwmac_tx_start(gnrc_netif2_t *netif,
gnrc_pktsnip_t *pkt,
gnrc_mac_tx_neighbor_t *neighbor);
/**
* @brief Stop LWMAC TX procedure
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif ptr to the network interface
*
*/
void gnrc_lwmac_tx_stop(gnrc_netdev_t *gnrc_netdev);
void gnrc_lwmac_tx_stop(gnrc_netif2_t *netif);
/**
* @brief Update LWMAC TX procedure for transmission
*
* @param[in,out] gnrc_netdev gnrc_netdev structure
* @param[in,out] netif ptr to the network interface
*
*/
void gnrc_lwmac_tx_update(gnrc_netdev_t *gnrc_netdev);
void gnrc_lwmac_tx_update(gnrc_netif2_t *netif);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -27,10 +27,97 @@
#include "net/gnrc/netdev.h"
#include "net/gnrc/lwmac/lwmac.h"
#include "include/lwmac_internal.h"
#include "net/gnrc/netif2/ieee802154.h"
#include "net/netdev/ieee802154.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
int _gnrc_lwmac_transmit(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt)
{
netdev_t *dev = netif->dev;
netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev;
gnrc_netif_hdr_t *netif_hdr;
gnrc_pktsnip_t *vec_snip;
const uint8_t *src, *dst = NULL;
int res = 0;
size_t n, src_len, dst_len;
uint8_t mhr[IEEE802154_MAX_HDR_LEN];
uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK);
le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan));
flags |= IEEE802154_FCF_TYPE_DATA;
if (pkt == NULL) {
DEBUG("_send_ieee802154: pkt was NULL\n");
return -EINVAL;
}
if (pkt->type != GNRC_NETTYPE_NETIF) {
DEBUG("_send_ieee802154: first header is not generic netif header\n");
return -EBADMSG;
}
netif_hdr = pkt->data;
/* prepare destination address */
if (netif_hdr->flags & /* If any of these flags is set assume broadcast */
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
dst = ieee802154_addr_bcast;
dst_len = IEEE802154_ADDR_BCAST_LEN;
}
else {
dst = gnrc_netif_hdr_get_dst_addr(netif_hdr);
dst_len = netif_hdr->dst_l2addr_len;
}
src_len = netif_hdr->src_l2addr_len;
if (src_len > 0) {
src = gnrc_netif_hdr_get_src_addr(netif_hdr);
}
else {
src_len = netif->l2addr_len;
src = netif->l2addr;
}
/* fill MAC header, seq should be set by device */
if ((res = ieee802154_set_frame_hdr(mhr, src, src_len,
dst, dst_len, dev_pan,
dev_pan, flags, state->seq++)) == 0) {
DEBUG("_send_ieee802154: Error preperaring frame\n");
return -EINVAL;
}
/* prepare packet for sending */
vec_snip = gnrc_pktbuf_get_iovec(pkt, &n);
if (vec_snip != NULL) {
struct iovec *vector;
pkt = vec_snip; /* reassign for later release; vec_snip is prepended to pkt */
vector = (struct iovec *)pkt->data;
vector[0].iov_base = mhr;
vector[0].iov_len = (size_t)res;
#ifdef MODULE_NETSTATS_L2
if (netif_hdr->flags &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
netif->dev->stats.tx_mcast_count++;
}
else {
netif->dev->stats.tx_unicast_count++;
}
#endif
#ifdef MODULE_GNRC_MAC
if (netif->mac.mac_info & GNRC_NETDEV_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, vector, n, &netif->mac.csma_conf);
}
else {
res = dev->driver->send(dev, vector, n);
}
#else
res = dev->driver->send(dev, vector, n);
#endif
}
else {
return -ENOBUFS;
}
/* release old data */
gnrc_pktbuf_release(pkt);
return res;
}
int _gnrc_lwmac_parse_packet(gnrc_pktsnip_t *pkt, gnrc_lwmac_packet_info_t *info)
{
gnrc_netif_hdr_t *netif_hdr;
@ -103,42 +190,42 @@ int _gnrc_lwmac_parse_packet(gnrc_pktsnip_t *pkt, gnrc_lwmac_packet_info_t *info
return 0;
}
void _gnrc_lwmac_set_netdev_state(gnrc_netdev_t *gnrc_netdev, netopt_state_t devstate)
void _gnrc_lwmac_set_netdev_state(gnrc_netif2_t *netif, netopt_state_t devstate)
{
gnrc_netdev->dev->driver->set(gnrc_netdev->dev,
NETOPT_STATE,
&devstate,
sizeof(devstate));
netif->dev->driver->set(netif->dev,
NETOPT_STATE,
&devstate,
sizeof(devstate));
#if (GNRC_LWMAC_ENABLE_DUTYCYLE_RECORD == 1)
if (devstate == NETOPT_STATE_IDLE) {
if (!(gnrc_netdev->lwmac.lwmac_info & GNRC_LWMAC_RADIO_IS_ON)) {
gnrc_netdev->lwmac.last_radio_on_time_ticks = rtt_get_counter();
gnrc_netdev->lwmac.lwmac_info |= GNRC_LWMAC_RADIO_IS_ON;
if (!(netif->mac.lwmac.lwmac_info & GNRC_LWMAC_RADIO_IS_ON)) {
netif->mac.lwmac.last_radio_on_time_ticks = rtt_get_counter();
netif->mac.lwmac.lwmac_info |= GNRC_LWMAC_RADIO_IS_ON;
}
return;
}
else if ((devstate == NETOPT_STATE_SLEEP) &&
(gnrc_netdev->lwmac.lwmac_info & GNRC_LWMAC_RADIO_IS_ON)) {
gnrc_netdev->lwmac.radio_off_time_ticks = rtt_get_counter();
(netif->mac.lwmac.lwmac_info & GNRC_LWMAC_RADIO_IS_ON)) {
netif->mac.lwmac.radio_off_time_ticks = rtt_get_counter();
gnrc_netdev->lwmac.awake_duration_sum_ticks +=
(gnrc_netdev->lwmac.radio_off_time_ticks -
gnrc_netdev->lwmac.last_radio_on_time_ticks);
netif->mac.lwmac.awake_duration_sum_ticks +=
(netif->mac.lwmac.radio_off_time_ticks -
netif->mac.lwmac.last_radio_on_time_ticks);
gnrc_netdev->lwmac.lwmac_info &= ~GNRC_LWMAC_RADIO_IS_ON;
netif->mac.lwmac.lwmac_info &= ~GNRC_LWMAC_RADIO_IS_ON;
}
#endif
}
netopt_state_t _gnrc_lwmac_get_netdev_state(gnrc_netdev_t *gnrc_netdev)
netopt_state_t _gnrc_lwmac_get_netdev_state(gnrc_netif2_t *netif)
{
netopt_state_t state;
if (0 < gnrc_netdev->dev->driver->get(gnrc_netdev->dev,
NETOPT_STATE,
&state,
sizeof(state))) {
if (0 < netif->dev->driver->get(netif->dev,
NETOPT_STATE,
&state,
sizeof(state))) {
return state;
}
return -1;
@ -165,23 +252,23 @@ int _gnrc_lwmac_dispatch_defer(gnrc_pktsnip_t *buffer[], gnrc_pktsnip_t *pkt)
return 0;
}
else if (bcast &&
(((gnrc_lwmac_hdr_t *)buffer[i]->next->data)->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) &&
(bcast->seq_nr == ((gnrc_lwmac_frame_broadcast_t *)buffer[i]->next->data)->seq_nr)) {
/* Filter same broadcasts, compare sequence number */
gnrc_netif_hdr_t *hdr_queued, *hdr_new;
hdr_new = pkt->next->next->data;
hdr_queued = buffer[i]->next->next->data;
(((gnrc_lwmac_hdr_t *)buffer[i]->next->data)->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) &&
(bcast->seq_nr == ((gnrc_lwmac_frame_broadcast_t *)buffer[i]->next->data)->seq_nr)) {
/* Filter same broadcasts, compare sequence number */
gnrc_netif_hdr_t *hdr_queued, *hdr_new;
hdr_new = pkt->next->next->data;
hdr_queued = buffer[i]->next->next->data;
/* Sequence numbers match, compare source addresses */
if ((hdr_new->src_l2addr_len == hdr_queued->src_l2addr_len) &&
(memcmp(gnrc_netif_hdr_get_src_addr(hdr_new),
gnrc_netif_hdr_get_src_addr(hdr_queued),
hdr_new->src_l2addr_len) == 0)) {
/* Source addresses match, same packet */
DEBUG("[LWMAC] Found duplicate broadcast packet, dropping\n");
gnrc_pktbuf_release(pkt);
return -2;
}
/* Sequence numbers match, compare source addresses */
if ((hdr_new->src_l2addr_len == hdr_queued->src_l2addr_len) &&
(memcmp(gnrc_netif_hdr_get_src_addr(hdr_new),
gnrc_netif_hdr_get_src_addr(hdr_queued),
hdr_new->src_l2addr_len) == 0)) {
/* Source addresses match, same packet */
DEBUG("[LWMAC] Found duplicate broadcast packet, dropping\n");
gnrc_pktbuf_release(pkt);
return -2;
}
}
}

View File

@ -52,14 +52,14 @@
*/
#define GNRC_LWMAC_RX_FOUND_DATA (0x04U)
static uint8_t _packet_process_in_wait_for_wr(gnrc_netdev_t *gnrc_netdev)
static uint8_t _packet_process_in_wait_for_wr(gnrc_netif2_t *netif)
{
uint8_t rx_info = 0;
gnrc_pktsnip_t *pkt;
assert(gnrc_netdev != NULL);
assert(netif != NULL);
while ((pkt = gnrc_priority_pktqueue_pop(&gnrc_netdev->rx.queue)) != NULL) {
while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) {
LOG_DEBUG("[LWMAC-rx] Inspecting pkt @ %p\n", pkt);
/* Parse packet */
@ -72,13 +72,13 @@ static uint8_t _packet_process_in_wait_for_wr(gnrc_netdev_t *gnrc_netdev)
}
if (info.header->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) {
_gnrc_lwmac_dispatch_defer(gnrc_netdev->rx.dispatch_buffer, pkt);
gnrc_mac_dispatch(&gnrc_netdev->rx);
_gnrc_lwmac_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
gnrc_mac_dispatch(&netif->mac.rx);
rx_info |= GNRC_LWMAC_RX_FOUND_BROADCAST;
/* quit listening period to avoid receiving duplicate broadcast packets */
gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true);
gnrc_lwmac_set_quit_rx(netif, true);
/* quit TX in this cycle to avoid collisions with broadcast packets */
gnrc_netdev_lwmac_set_quit_tx(gnrc_netdev, true);
gnrc_lwmac_set_quit_tx(netif, true);
break;
}
@ -91,18 +91,18 @@ static uint8_t _packet_process_in_wait_for_wr(gnrc_netdev_t *gnrc_netdev)
/* No need to keep pkt anymore */
gnrc_pktbuf_release(pkt);
if (!(memcmp(&info.dst_addr.addr, &gnrc_netdev->l2_addr,
gnrc_netdev->l2_addr_len) == 0)) {
if (!(memcmp(&info.dst_addr.addr, &netif->l2addr,
netif->l2addr_len) == 0)) {
LOG_DEBUG("[LWMAC-rx] Packet is WR but not for us\n");
/* quit TX in this cycle to avoid collisions with other senders, since
* found ongoing WR (preamble) stream */
gnrc_netdev_lwmac_set_quit_tx(gnrc_netdev, true);
gnrc_lwmac_set_quit_tx(netif, true);
continue;
}
/* If reach here, the node gets a WR for itself. */
/* Save source address for later addressing */
gnrc_netdev->rx.l2_addr = info.src_addr;
netif->mac.rx.l2_addr = info.src_addr;
rx_info |= GNRC_LWMAC_RX_FOUND_WR;
break;
@ -112,56 +112,56 @@ static uint8_t _packet_process_in_wait_for_wr(gnrc_netdev_t *gnrc_netdev)
}
/* return false if send wa failed, otherwise return true */
static bool _send_wa(gnrc_netdev_t *gnrc_netdev)
static bool _send_wa(gnrc_netif2_t *netif)
{
gnrc_pktsnip_t *pkt;
gnrc_pktsnip_t *pkt_lwmac;
gnrc_netif_hdr_t *nethdr_wa;
assert(gnrc_netdev != NULL);
assert(gnrc_netdev->rx.l2_addr.len != 0);
assert(netif != NULL);
assert(netif->mac.rx.l2_addr.len != 0);
/* if found ongoing transmission,
* quit sending WA for collision avoidance. */
if (_gnrc_lwmac_get_netdev_state(gnrc_netdev) == NETOPT_STATE_RX) {
gnrc_netdev->rx.rx_bad_exten_count++;
if (_gnrc_lwmac_get_netdev_state(netif) == NETOPT_STATE_RX) {
netif->mac.rx.rx_bad_exten_count++;
return false;
}
/* Assemble WA packet */
gnrc_lwmac_frame_wa_t lwmac_hdr;
lwmac_hdr.header.type = GNRC_LWMAC_FRAMETYPE_WA;
lwmac_hdr.dst_addr = gnrc_netdev->rx.l2_addr;
lwmac_hdr.dst_addr = netif->mac.rx.l2_addr;
uint32_t phase_now = _gnrc_lwmac_phase_now();
/* Embed the current 'relative phase timing' (counted from the start of this cycle)
* of the receiver into its WA packet, thus to allow the sender to infer the
* receiver's exact wake-up timing */
if (phase_now > _gnrc_lwmac_ticks_to_phase(gnrc_netdev->lwmac.last_wakeup)) {
if (phase_now > _gnrc_lwmac_ticks_to_phase(netif->mac.lwmac.last_wakeup)) {
lwmac_hdr.current_phase = (phase_now -
_gnrc_lwmac_ticks_to_phase(gnrc_netdev->lwmac.last_wakeup));
_gnrc_lwmac_ticks_to_phase(netif->mac.lwmac.last_wakeup));
}
else {
lwmac_hdr.current_phase = (phase_now + RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)) -
_gnrc_lwmac_ticks_to_phase(gnrc_netdev->lwmac.last_wakeup);
_gnrc_lwmac_ticks_to_phase(netif->mac.lwmac.last_wakeup);
}
pkt = gnrc_pktbuf_add(NULL, &lwmac_hdr, sizeof(lwmac_hdr), GNRC_NETTYPE_LWMAC);
if (pkt == NULL) {
LOG_ERROR("ERROR: [LWMAC-rx] Cannot allocate pktbuf of type GNRC_NETTYPE_LWMAC\n");
gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true);
gnrc_lwmac_set_quit_rx(netif, true);
return false;
}
pkt_lwmac = pkt;
pkt = gnrc_pktbuf_add(pkt, NULL,
sizeof(gnrc_netif_hdr_t) + gnrc_netdev->rx.l2_addr.len,
sizeof(gnrc_netif_hdr_t) + netif->mac.rx.l2_addr.len,
GNRC_NETTYPE_NETIF);
if (pkt == NULL) {
LOG_ERROR("ERROR: [LWMAC-rx] Cannot allocate pktbuf of type GNRC_NETTYPE_NETIF\n");
gnrc_pktbuf_release(pkt_lwmac);
gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true);
gnrc_lwmac_set_quit_rx(netif, true);
return false;
}
@ -170,44 +170,44 @@ static bool _send_wa(gnrc_netdev_t *gnrc_netdev)
nethdr_wa = (gnrc_netif_hdr_t *)(gnrc_pktsnip_search_type(pkt,
GNRC_NETTYPE_NETIF)->data);
/* Construct NETIF header and insert address for WA packet */
gnrc_netif_hdr_init(nethdr_wa, 0, gnrc_netdev->rx.l2_addr.len);
gnrc_netif_hdr_init(nethdr_wa, 0, netif->mac.rx.l2_addr.len);
/* Send WA as broadcast*/
nethdr_wa->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST;
/* Disable Auto ACK */
netopt_enable_t autoack = NETOPT_DISABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_AUTOACK, &autoack,
sizeof(autoack));
netif->dev->driver->set(netif->dev, NETOPT_AUTOACK, &autoack,
sizeof(autoack));
/* Send WA */
if (gnrc_netdev->send(gnrc_netdev, pkt) < 0) {
if (_gnrc_lwmac_transmit(netif, pkt) < 0) {
LOG_ERROR("ERROR: [LWMAC-rx] Send WA failed.");
if (pkt != NULL) {
gnrc_pktbuf_release(pkt);
}
gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true);
gnrc_lwmac_set_quit_rx(netif, true);
return false;
}
/* Enable Auto ACK again for data reception */
autoack = NETOPT_ENABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_AUTOACK, &autoack,
sizeof(autoack));
netif->dev->driver->set(netif->dev, NETOPT_AUTOACK, &autoack,
sizeof(autoack));
return true;
}
static uint8_t _packet_process_in_wait_for_data(gnrc_netdev_t *gnrc_netdev)
static uint8_t _packet_process_in_wait_for_data(gnrc_netif2_t *netif)
{
uint8_t rx_info = 0;
gnrc_pktsnip_t *pkt;
assert(gnrc_netdev != NULL);
assert(netif != NULL);
pkt = NULL;
while ((pkt = gnrc_priority_pktqueue_pop(&gnrc_netdev->rx.queue)) != NULL) {
while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) {
LOG_DEBUG("[LWMAC-rx] Inspecting pkt @ %p\n", pkt);
/* Parse packet */
@ -220,40 +220,40 @@ static uint8_t _packet_process_in_wait_for_data(gnrc_netdev_t *gnrc_netdev)
}
if (info.header->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) {
_gnrc_lwmac_dispatch_defer(gnrc_netdev->rx.dispatch_buffer, pkt);
gnrc_mac_dispatch(&gnrc_netdev->rx);
_gnrc_lwmac_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
gnrc_mac_dispatch(&netif->mac.rx);
/* quit listening period to avoid receiving duplicate broadcast packets */
gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true);
gnrc_lwmac_set_quit_rx(netif, true);
continue;
}
if (!(memcmp(&info.src_addr.addr, &gnrc_netdev->rx.l2_addr.addr,
gnrc_netdev->rx.l2_addr.len) == 0)) {
if (!(memcmp(&info.src_addr.addr, &netif->mac.rx.l2_addr.addr,
netif->mac.rx.l2_addr.len) == 0)) {
LOG_DEBUG("[LWMAC-rx] Packet is not from destination\n");
gnrc_pktbuf_release(pkt);
/* Reset timeout to wait for the data packet */
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA);
gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
continue;
}
if (!(memcmp(&info.dst_addr.addr, &gnrc_netdev->l2_addr,
gnrc_netdev->l2_addr_len) == 0)) {
if (!(memcmp(&info.dst_addr.addr, &netif->l2addr,
netif->l2addr_len) == 0)) {
LOG_DEBUG("[LWMAC-rx] Packet is not for us\n");
gnrc_pktbuf_release(pkt);
/* Reset timeout to wait for the data packet */
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA);
gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
continue;
}
/* Sender maybe didn't get the WA */
if (info.header->type == GNRC_LWMAC_FRAMETYPE_WR) {
LOG_DEBUG("[LWMAC-rx] Found a WR while waiting for DATA\n");
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA);
rx_info |= GNRC_LWMAC_RX_FOUND_WR;
/* Push WR back to rx queue */
gnrc_mac_queue_rx_packet(&gnrc_netdev->rx, 0, pkt);
gnrc_mac_queue_rx_packet(&netif->mac.rx, 0, pkt);
break;
}
@ -261,10 +261,10 @@ static uint8_t _packet_process_in_wait_for_data(gnrc_netdev_t *gnrc_netdev)
case GNRC_LWMAC_FRAMETYPE_DATA:
case GNRC_LWMAC_FRAMETYPE_DATA_PENDING: {
/* Receiver gets the data packet */
_gnrc_lwmac_dispatch_defer(gnrc_netdev->rx.dispatch_buffer, pkt);
gnrc_mac_dispatch(&gnrc_netdev->rx);
_gnrc_lwmac_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
gnrc_mac_dispatch(&netif->mac.rx);
LOG_DEBUG("[LWMAC-rx] Found DATA!\n");
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA);
rx_info |= GNRC_LWMAC_RX_FOUND_DATA;
return rx_info;
}
@ -277,117 +277,117 @@ static uint8_t _packet_process_in_wait_for_data(gnrc_netdev_t *gnrc_netdev)
return rx_info;
}
void gnrc_lwmac_rx_start(gnrc_netdev_t *gnrc_netdev)
void gnrc_lwmac_rx_start(gnrc_netif2_t *netif)
{
if (gnrc_netdev == NULL) {
if (netif == NULL) {
return;
}
/* RX address should have been reset, probably not stopped then */
assert(gnrc_netdev->rx.l2_addr.len == 0);
assert(netif->mac.rx.l2_addr.len == 0);
/* Don't attempt to send a WA if channel is busy to get timings right */
gnrc_netdev->mac_info &= ~GNRC_NETDEV_MAC_INFO_CSMA_ENABLED;
netif->mac.mac_info &= ~GNRC_NETIF2_MAC_INFO_CSMA_ENABLED;
netopt_enable_t csma_disable = NETOPT_DISABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_CSMA, &csma_disable,
sizeof(csma_disable));
netif->dev->driver->set(netif->dev, NETOPT_CSMA, &csma_disable,
sizeof(csma_disable));
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_INIT;
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_INIT;
}
void gnrc_lwmac_rx_stop(gnrc_netdev_t *gnrc_netdev)
void gnrc_lwmac_rx_stop(gnrc_netif2_t *netif)
{
if (!gnrc_netdev) {
if (!netif) {
return;
}
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_STOPPED;
gnrc_netdev->rx.l2_addr.len = 0;
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA);
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_STOPPED;
netif->mac.rx.l2_addr.len = 0;
}
/* Returns whether rescheduling is needed or not */
static bool _lwmac_rx_update(gnrc_netdev_t *gnrc_netdev)
static bool _lwmac_rx_update(gnrc_netif2_t *netif)
{
bool reschedule = false;
if (!gnrc_netdev) {
if (!netif) {
return reschedule;
}
switch (gnrc_netdev->rx.state) {
switch (netif->mac.rx.state) {
case GNRC_LWMAC_RX_STATE_INIT: {
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA);
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_WAIT_FOR_WR;
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA);
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_WAIT_FOR_WR;
reschedule = true;
break;
}
case GNRC_LWMAC_RX_STATE_WAIT_FOR_WR: {
LOG_DEBUG("[LWMAC-rx] GNRC_LWMAC_RX_STATE_WAIT_FOR_WR\n");
uint8_t rx_info = _packet_process_in_wait_for_wr(gnrc_netdev);
uint8_t rx_info = _packet_process_in_wait_for_wr(netif);
/* if found broadcast packet, goto rx successful */
if (rx_info & GNRC_LWMAC_RX_FOUND_BROADCAST) {
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_SUCCESSFUL;
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_SUCCESSFUL;
reschedule = true;
break;
}
if (!(rx_info & GNRC_LWMAC_RX_FOUND_WR)) {
LOG_DEBUG("[LWMAC-rx] No WR found, stop RX\n");
gnrc_netdev->rx.rx_bad_exten_count++;
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_FAILED;
netif->mac.rx.rx_bad_exten_count++;
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_FAILED;
reschedule = true;
break;
}
gnrc_priority_pktqueue_flush(&gnrc_netdev->rx.queue);
gnrc_priority_pktqueue_flush(&netif->mac.rx.queue);
/* Found WR packet (preamble), goto next state to send WA (preamble-ACK) */
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_SEND_WA;
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_SEND_WA;
reschedule = true;
break;
}
case GNRC_LWMAC_RX_STATE_SEND_WA: {
LOG_DEBUG("[LWMAC-rx] GNRC_LWMAC_RX_STATE_SEND_WA\n");
if (!_send_wa(gnrc_netdev)) {
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_FAILED;
if (!_send_wa(netif)) {
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_FAILED;
reschedule = true;
break;
}
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_WAIT_WA_SENT;
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_WAIT_WA_SENT;
reschedule = false;
break;
}
case GNRC_LWMAC_RX_STATE_WAIT_WA_SENT: {
LOG_DEBUG("[LWMAC-rx] GNRC_LWMAC_RX_STATE_WAIT_WA_SENT\n");
if (gnrc_netdev_get_tx_feedback(gnrc_netdev) == TX_FEEDBACK_UNDEF) {
if (gnrc_netif2_get_tx_feedback(netif) == TX_FEEDBACK_UNDEF) {
LOG_DEBUG("[LWMAC-rx] WA not yet completely sent\n");
break;
}
/* When reach here, WA has been sent, set timeout for expected data arrival */
gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
_gnrc_lwmac_set_netdev_state(gnrc_netdev, NETOPT_STATE_IDLE);
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_WAIT_FOR_DATA;
_gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE);
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_WAIT_FOR_DATA;
reschedule = false;
break;
}
case GNRC_LWMAC_RX_STATE_WAIT_FOR_DATA: {
LOG_DEBUG("[LWMAC-rx] GNRC_LWMAC_RX_STATE_WAIT_FOR_DATA\n");
uint8_t rx_info = _packet_process_in_wait_for_data(gnrc_netdev);
uint8_t rx_info = _packet_process_in_wait_for_data(netif);
/* If WA got lost we wait for data but we will be hammered with WR
* packets. So a WR indicates a lost WA => reset RX state machine. */
if (rx_info & GNRC_LWMAC_RX_FOUND_WR) {
LOG_INFO("[LWMAC-rx] WA probably got lost, reset RX state machine\n");
/* Start over again */
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_INIT;
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_INIT;
reschedule = true;
break;
}
@ -396,16 +396,16 @@ static bool _lwmac_rx_update(gnrc_netdev_t *gnrc_netdev)
* received. This won't be blocked by WRs as they restart the state
* machine (see above).
*/
if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA)) {
if (!gnrc_netdev_get_rx_started(gnrc_netdev)) {
if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_DATA)) {
if (!gnrc_netif2_get_rx_started(netif)) {
LOG_INFO("[LWMAC-rx] DATA timed out\n");
gnrc_netdev->rx.rx_bad_exten_count++;
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_FAILED;
netif->mac.rx.rx_bad_exten_count++;
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_FAILED;
reschedule = true;
}
else {
/* If radio is receiving packet, reset wait data timeout */
gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA, GNRC_LWMAC_DATA_DELAY_US);
}
break;
}
@ -415,7 +415,7 @@ static bool _lwmac_rx_update(gnrc_netdev_t *gnrc_netdev)
break;
}
gnrc_netdev->rx.state = GNRC_LWMAC_RX_STATE_SUCCESSFUL;
netif->mac.rx.state = GNRC_LWMAC_RX_STATE_SUCCESSFUL;
reschedule = true;
break;
}
@ -430,8 +430,8 @@ static bool _lwmac_rx_update(gnrc_netdev_t *gnrc_netdev)
return reschedule;
}
void gnrc_lwmac_rx_update(gnrc_netdev_t *gnrc_netdev)
void gnrc_lwmac_rx_update(gnrc_netif2_t *netif)
{
/* Update until no rescheduling needed */
while (_lwmac_rx_update(gnrc_netdev)) {}
while (_lwmac_rx_update(netif)) {}
}

View File

@ -58,40 +58,40 @@ static int _lwmac_find_timeout(gnrc_lwmac_t *lwmac, gnrc_lwmac_timeout_type_t ty
return -ENOENT;
}
inline bool gnrc_lwmac_timeout_is_running(gnrc_netdev_t *gnrc_netdev,
inline bool gnrc_lwmac_timeout_is_running(gnrc_netif2_t *netif,
gnrc_lwmac_timeout_type_t type)
{
assert(gnrc_netdev);
return (_lwmac_find_timeout(&gnrc_netdev->lwmac, type) >= 0);
assert(netif);
return (_lwmac_find_timeout(&netif->mac.lwmac, type) >= 0);
}
bool gnrc_lwmac_timeout_is_expired(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_timeout_type_t type)
bool gnrc_lwmac_timeout_is_expired(gnrc_netif2_t *netif, gnrc_lwmac_timeout_type_t type)
{
assert(gnrc_netdev);
assert(netif);
int index = _lwmac_find_timeout(&gnrc_netdev->lwmac, type);
int index = _lwmac_find_timeout(&netif->mac.lwmac, type);
if (index >= 0) {
if (gnrc_netdev->lwmac.timeouts[index].expired) {
_lwmac_clear_timeout(&gnrc_netdev->lwmac.timeouts[index]);
if (netif->mac.lwmac.timeouts[index].expired) {
_lwmac_clear_timeout(&netif->mac.lwmac.timeouts[index]);
}
return gnrc_netdev->lwmac.timeouts[index].expired;
return netif->mac.lwmac.timeouts[index].expired;
}
return false;
}
gnrc_lwmac_timeout_t *_lwmac_acquire_timeout(gnrc_netdev_t *gnrc_netdev,
gnrc_lwmac_timeout_t *_lwmac_acquire_timeout(gnrc_netif2_t *netif,
gnrc_lwmac_timeout_type_t type)
{
assert(gnrc_netdev);
assert(netif);
if (gnrc_lwmac_timeout_is_running(gnrc_netdev, type)) {
if (gnrc_lwmac_timeout_is_running(netif, type)) {
return NULL;
}
for (unsigned i = 0; i < GNRC_LWMAC_TIMEOUT_COUNT; i++) {
if (gnrc_netdev->lwmac.timeouts[i].type == GNRC_LWMAC_TIMEOUT_DISABLED) {
gnrc_netdev->lwmac.timeouts[i].type = type;
return &gnrc_netdev->lwmac.timeouts[i];
if (netif->mac.lwmac.timeouts[i].type == GNRC_LWMAC_TIMEOUT_DISABLED) {
netif->mac.lwmac.timeouts[i].type = type;
return &netif->mac.lwmac.timeouts[i];
}
}
return NULL;
@ -104,31 +104,31 @@ void gnrc_lwmac_timeout_make_expire(gnrc_lwmac_timeout_t *timeout)
timeout->expired = true;
}
void gnrc_lwmac_clear_timeout(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_timeout_type_t type)
void gnrc_lwmac_clear_timeout(gnrc_netif2_t *netif, gnrc_lwmac_timeout_type_t type)
{
assert(gnrc_netdev);
assert(netif);
int index = _lwmac_find_timeout(&gnrc_netdev->lwmac, type);
int index = _lwmac_find_timeout(&netif->mac.lwmac, type);
if (index >= 0) {
_lwmac_clear_timeout(&gnrc_netdev->lwmac.timeouts[index]);
_lwmac_clear_timeout(&netif->mac.lwmac.timeouts[index]);
}
}
void gnrc_lwmac_set_timeout(gnrc_netdev_t *gnrc_netdev,
void gnrc_lwmac_set_timeout(gnrc_netif2_t *netif,
gnrc_lwmac_timeout_type_t type,
uint32_t offset)
{
assert(gnrc_netdev);
assert(netif);
gnrc_lwmac_timeout_t *timeout;
if ((timeout = _lwmac_acquire_timeout(gnrc_netdev, type))) {
if ((timeout = _lwmac_acquire_timeout(netif, type))) {
DEBUG("[LWMAC] Set timeout %s in %" PRIu32 " us\n",
lwmac_timeout_names[type], offset);
timeout->expired = false;
timeout->msg.type = GNRC_LWMAC_EVENT_TIMEOUT_TYPE;
timeout->msg.content.ptr = (void *) timeout;
xtimer_set_msg(&(timeout->timer), offset,
&(timeout->msg), gnrc_netdev->pid);
&(timeout->msg), netif->pid);
}
else {
DEBUG("[LWMAC] Cannot set timeout %s, too many concurrent timeouts\n",
@ -136,13 +136,13 @@ void gnrc_lwmac_set_timeout(gnrc_netdev_t *gnrc_netdev,
}
}
void gnrc_lwmac_reset_timeouts(gnrc_netdev_t *gnrc_netdev)
void gnrc_lwmac_reset_timeouts(gnrc_netif2_t *netif)
{
assert(gnrc_netdev);
assert(netif);
for (unsigned i = 0; i < GNRC_LWMAC_TIMEOUT_COUNT; i++) {
if (gnrc_netdev->lwmac.timeouts[i].type != GNRC_LWMAC_TIMEOUT_DISABLED) {
_lwmac_clear_timeout(&gnrc_netdev->lwmac.timeouts[i]);
if (netif->mac.lwmac.timeouts[i].type != GNRC_LWMAC_TIMEOUT_DISABLED) {
_lwmac_clear_timeout(&netif->mac.lwmac.timeouts[i]);
}
}
}

View File

@ -49,77 +49,77 @@
*/
#define GNRC_LWMAC_TX_FAIL (0x02U)
static uint8_t _send_bcast(gnrc_netdev_t *gnrc_netdev)
static uint8_t _send_bcast(gnrc_netif2_t *netif)
{
assert(gnrc_netdev != NULL);
assert(netif != NULL);
uint8_t tx_info = 0;
gnrc_pktsnip_t *pkt = gnrc_netdev->tx.packet;
gnrc_pktsnip_t *pkt = netif->mac.tx.packet;
bool first = false;
if (gnrc_lwmac_timeout_is_running(gnrc_netdev, GNRC_LWMAC_TIMEOUT_BROADCAST_END)) {
if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_BROADCAST_END)) {
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST);
if (gnrc_lwmac_timeout_is_running(netif, GNRC_LWMAC_TIMEOUT_BROADCAST_END)) {
if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_BROADCAST_END)) {
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST);
gnrc_pktbuf_release(pkt);
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
tx_info |= GNRC_LWMAC_TX_SUCCESS;
return tx_info;
}
}
else {
LOG_INFO("[LWMAC-tx] Initialize broadcasting\n");
gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_BROADCAST_END,
GNRC_LWMAC_BROADCAST_DURATION_US);
gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_BROADCAST_END,
GNRC_LWMAC_BROADCAST_DURATION_US);
gnrc_pktsnip_t *pkt_payload;
/* Prepare packet with LWMAC header*/
gnrc_lwmac_frame_broadcast_t hdr = {};
hdr.header.type = GNRC_LWMAC_FRAMETYPE_BROADCAST;
hdr.seq_nr = gnrc_netdev->tx.bcast_seqnr++;
hdr.seq_nr = netif->mac.tx.bcast_seqnr++;
pkt_payload = pkt->next;
pkt->next = gnrc_pktbuf_add(pkt->next, &hdr, sizeof(hdr), GNRC_NETTYPE_LWMAC);
if (pkt->next == NULL) {
LOG_ERROR("ERROR: [LWMAC-tx] Cannot allocate pktbuf of type FRAMETYPE_BROADCAST\n");
gnrc_netdev->tx.packet->next = pkt_payload;
netif->mac.tx.packet->next = pkt_payload;
/* Drop the broadcast packet */
LOG_ERROR("ERROR: [LWMAC-tx] Memory maybe full, drop the broadcast packet\n");
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
gnrc_pktbuf_release(netif->mac.tx.packet);
/* clear packet point to avoid TX retry */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
tx_info |= GNRC_LWMAC_TX_FAIL;
return tx_info;
}
/* No Auto-ACK for broadcast packets */
netopt_enable_t autoack = NETOPT_DISABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_AUTOACK, &autoack,
sizeof(autoack));
netif->dev->driver->set(netif->dev, NETOPT_AUTOACK, &autoack,
sizeof(autoack));
first = true;
}
if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST) ||
if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST) ||
first) {
/* if found ongoing transmission, quit this cycle for collision avoidance.
* Broadcast packet will be re-queued and try to send in the next cycle. */
if (_gnrc_lwmac_get_netdev_state(gnrc_netdev) == NETOPT_STATE_RX) {
* Broadcast packet will be re-queued and try to send in the next cycle. */
if (_gnrc_lwmac_get_netdev_state(netif) == NETOPT_STATE_RX) {
/* save pointer to netif header */
gnrc_pktsnip_t *netif = pkt->next->next;
gnrc_pktsnip_t *netif_snip = pkt->next->next;
/* remove LWMAC header */
pkt->next->next = NULL;
gnrc_pktbuf_release(pkt->next);
/* make append netif header after payload again */
pkt->next = netif;
pkt->next = netif_snip;
if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, gnrc_netdev->tx.packet)) {
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
}
/* drop pointer so it wont be free'd */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
tx_info |= GNRC_LWMAC_TX_FAIL;
return tx_info;
}
@ -127,24 +127,24 @@ static uint8_t _send_bcast(gnrc_netdev_t *gnrc_netdev)
/* Don't let the packet be released yet, we want to send it again */
gnrc_pktbuf_hold(pkt, 1);
int res = gnrc_netdev->send(gnrc_netdev, pkt);
int res = _gnrc_lwmac_transmit(netif, pkt);
if (res < 0) {
LOG_ERROR("ERROR: [LWMAC-tx] Send broadcast pkt failed.");
tx_info |= GNRC_LWMAC_TX_FAIL;
return tx_info;
}
gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST,
GNRC_LWMAC_TIME_BETWEEN_BROADCAST_US);
gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST,
GNRC_LWMAC_TIME_BETWEEN_BROADCAST_US);
LOG_INFO("[LWMAC-tx] Broadcast sent\n");
}
return tx_info;
}
static uint8_t _send_wr(gnrc_netdev_t *gnrc_netdev)
static uint8_t _send_wr(gnrc_netif2_t *netif)
{
assert(gnrc_netdev != NULL);
assert(netif != NULL);
uint8_t tx_info = 0;
gnrc_pktsnip_t *pkt;
@ -153,13 +153,13 @@ static uint8_t _send_wr(gnrc_netdev_t *gnrc_netdev)
/* if found ongoing transmission, quit this cycle for collision avoidance.
* Data packet will be re-queued and try to send in the next cycle. */
if (_gnrc_lwmac_get_netdev_state(gnrc_netdev) == NETOPT_STATE_RX) {
if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, gnrc_netdev->tx.packet)) {
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
if (_gnrc_lwmac_get_netdev_state(netif) == NETOPT_STATE_RX) {
if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
}
/* drop pointer so it wont be free'd */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
tx_info |= GNRC_LWMAC_TX_FAIL;
return tx_info;
}
@ -167,17 +167,17 @@ static uint8_t _send_wr(gnrc_netdev_t *gnrc_netdev)
/* Assemble WR */
gnrc_lwmac_frame_wr_t wr_hdr = {};
wr_hdr.header.type = GNRC_LWMAC_FRAMETYPE_WR;
memcpy(&(wr_hdr.dst_addr.addr), gnrc_netdev->tx.current_neighbor->l2_addr,
gnrc_netdev->tx.current_neighbor->l2_addr_len);
wr_hdr.dst_addr.len = gnrc_netdev->tx.current_neighbor->l2_addr_len;
memcpy(&(wr_hdr.dst_addr.addr), netif->mac.tx.current_neighbor->l2_addr,
netif->mac.tx.current_neighbor->l2_addr_len);
wr_hdr.dst_addr.len = netif->mac.tx.current_neighbor->l2_addr_len;
pkt = gnrc_pktbuf_add(NULL, &wr_hdr, sizeof(wr_hdr), GNRC_NETTYPE_LWMAC);
if (pkt == NULL) {
LOG_ERROR("ERROR: [LWMAC-tx] Cannot allocate pktbuf of type GNRC_NETTYPE_LWMAC\n");
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_ERROR("ERROR: [LWMAC-tx] Memory maybe full, drop the data packet\n");
/* clear packet point to avoid TX retry */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
tx_info |= GNRC_LWMAC_TX_FAIL;
return tx_info;
}
@ -190,9 +190,9 @@ static uint8_t _send_wr(gnrc_netdev_t *gnrc_netdev)
LOG_ERROR("ERROR: [LWMAC-tx] Cannot allocate pktbuf of type GNRC_NETTYPE_NETIF\n");
gnrc_pktbuf_release(pkt_lwmac);
LOG_ERROR("ERROR: [LWMAC-tx] Memory maybe full, drop the data packet\n");
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
gnrc_pktbuf_release(netif->mac.tx.packet);
/* clear packet point to avoid TX retry */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
tx_info |= GNRC_LWMAC_TX_FAIL;
return tx_info;
}
@ -209,12 +209,12 @@ static uint8_t _send_wr(gnrc_netdev_t *gnrc_netdev)
/* Disable Auto ACK */
netopt_enable_t autoack = NETOPT_DISABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_AUTOACK, &autoack,
sizeof(autoack));
netif->dev->driver->set(netif->dev, NETOPT_AUTOACK, &autoack,
sizeof(autoack));
/* Prepare WR, this will discard any frame in the transceiver that has
* possibly arrived in the meantime but we don't care at this point. */
int res = gnrc_netdev->send(gnrc_netdev, pkt);
* possibly arrived in the meantime but we don't care at this point. */
int res = _gnrc_lwmac_transmit(netif, pkt);
if (res < 0) {
LOG_ERROR("ERROR: [LWMAC-tx] Send WR failed.");
if (pkt != NULL) {
@ -224,13 +224,13 @@ static uint8_t _send_wr(gnrc_netdev_t *gnrc_netdev)
return tx_info;
}
gnrc_priority_pktqueue_flush(&gnrc_netdev->rx.queue);
gnrc_priority_pktqueue_flush(&netif->mac.rx.queue);
return tx_info;
}
static uint8_t _packet_process_in_wait_for_wa(gnrc_netdev_t *gnrc_netdev)
static uint8_t _packet_process_in_wait_for_wa(gnrc_netif2_t *netif)
{
assert(gnrc_netdev != NULL);
assert(netif != NULL);
uint8_t tx_info = 0;
gnrc_pktsnip_t *pkt;
@ -238,7 +238,7 @@ static uint8_t _packet_process_in_wait_for_wa(gnrc_netdev_t *gnrc_netdev)
bool postponed = false;
bool from_expected_destination = false;
while ((pkt = gnrc_priority_pktqueue_pop(&gnrc_netdev->rx.queue)) != NULL) {
while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) {
LOG_DEBUG("[LWMAC-tx] Inspecting pkt @ %p\n", pkt);
/* Parse packet */
@ -251,14 +251,14 @@ static uint8_t _packet_process_in_wait_for_wa(gnrc_netdev_t *gnrc_netdev)
continue;
}
if (memcmp(&info.src_addr.addr, &gnrc_netdev->tx.current_neighbor->l2_addr,
gnrc_netdev->tx.current_neighbor->l2_addr_len) == 0) {
if (memcmp(&info.src_addr.addr, &netif->mac.tx.current_neighbor->l2_addr,
netif->mac.tx.current_neighbor->l2_addr_len) == 0) {
from_expected_destination = true;
}
if (info.header->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) {
_gnrc_lwmac_dispatch_defer(gnrc_netdev->rx.dispatch_buffer, pkt);
gnrc_mac_dispatch(&gnrc_netdev->rx);
_gnrc_lwmac_dispatch_defer(netif->mac.rx.dispatch_buffer, pkt);
gnrc_mac_dispatch(&netif->mac.rx);
/* Drop pointer to it can't get released */
pkt = NULL;
continue;
@ -267,14 +267,14 @@ static uint8_t _packet_process_in_wait_for_wa(gnrc_netdev_t *gnrc_netdev)
/* Check if destination is talking to another node. It will sleep
* after a finished transaction so there's no point in trying any
* further now. */
if (!(memcmp(&info.dst_addr.addr, &gnrc_netdev->l2_addr,
gnrc_netdev->l2_addr_len) == 0) && from_expected_destination) {
if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, gnrc_netdev->tx.packet)) {
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
if (!(memcmp(&info.dst_addr.addr, &netif->l2addr,
netif->l2addr_len) == 0) && from_expected_destination) {
if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
}
/* drop pointer so it wont be free'd */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
postponed = true;
gnrc_pktbuf_release(pkt);
break;
@ -283,12 +283,12 @@ static uint8_t _packet_process_in_wait_for_wa(gnrc_netdev_t *gnrc_netdev)
/* if found anther node is also trying to send data,
* quit this cycle for collision avoidance. */
if (info.header->type == GNRC_LWMAC_FRAMETYPE_WR) {
if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, gnrc_netdev->tx.packet)) {
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
}
/* drop pointer so it wont be free'd */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
postponed = true;
gnrc_pktbuf_release(pkt);
break;
@ -302,33 +302,33 @@ static uint8_t _packet_process_in_wait_for_wa(gnrc_netdev_t *gnrc_netdev)
if (from_expected_destination) {
/* calculate the phase of the receiver based on WA */
gnrc_netdev->tx.timestamp = _gnrc_lwmac_phase_now();
netif->mac.tx.timestamp = _gnrc_lwmac_phase_now();
gnrc_lwmac_frame_wa_t *wa_hdr;
wa_hdr = (gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_LWMAC))->data;
if (gnrc_netdev->tx.timestamp >= wa_hdr->current_phase) {
gnrc_netdev->tx.timestamp = gnrc_netdev->tx.timestamp -
wa_hdr->current_phase;
if (netif->mac.tx.timestamp >= wa_hdr->current_phase) {
netif->mac.tx.timestamp = netif->mac.tx.timestamp -
wa_hdr->current_phase;
}
else {
gnrc_netdev->tx.timestamp += RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US);
gnrc_netdev->tx.timestamp -= wa_hdr->current_phase;
netif->mac.tx.timestamp += RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US);
netif->mac.tx.timestamp -= wa_hdr->current_phase;
}
uint32_t own_phase;
own_phase = _gnrc_lwmac_ticks_to_phase(gnrc_netdev->lwmac.last_wakeup);
own_phase = _gnrc_lwmac_ticks_to_phase(netif->mac.lwmac.last_wakeup);
if (own_phase >= gnrc_netdev->tx.timestamp) {
own_phase = own_phase - gnrc_netdev->tx.timestamp;
if (own_phase >= netif->mac.tx.timestamp) {
own_phase = own_phase - netif->mac.tx.timestamp;
}
else {
own_phase = gnrc_netdev->tx.timestamp - own_phase;
own_phase = netif->mac.tx.timestamp - own_phase;
}
if ((own_phase < RTT_US_TO_TICKS((3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2))) ||
(own_phase > RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US -
(3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2)))) {
gnrc_netdev_lwmac_set_phase_backoff(gnrc_netdev, true);
gnrc_lwmac_set_phase_backoff(netif, true);
LOG_WARNING("WARNING: [LWMAC-tx] phase close\n");
}
}
@ -342,7 +342,7 @@ static uint8_t _packet_process_in_wait_for_wa(gnrc_netdev_t *gnrc_netdev)
}
/* All checks passed so this must be a valid WA */
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WR);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WR);
found_wa = true;
break;
@ -360,39 +360,39 @@ static uint8_t _packet_process_in_wait_for_wa(gnrc_netdev_t *gnrc_netdev)
}
/* Save newly calculated phase for destination */
gnrc_netdev->tx.current_neighbor->phase = gnrc_netdev->tx.timestamp;
LOG_INFO("[LWMAC-tx] New phase: %" PRIu32 "\n", gnrc_netdev->tx.timestamp);
netif->mac.tx.current_neighbor->phase = netif->mac.tx.timestamp;
LOG_INFO("[LWMAC-tx] New phase: %" PRIu32 "\n", netif->mac.tx.timestamp);
/* We've got our WA, so discard the rest, TODO: no flushing */
gnrc_priority_pktqueue_flush(&gnrc_netdev->rx.queue);
gnrc_priority_pktqueue_flush(&netif->mac.rx.queue);
tx_info |= GNRC_LWMAC_TX_SUCCESS;
return tx_info;
}
/* return false if send data failed, otherwise return true */
static bool _send_data(gnrc_netdev_t *gnrc_netdev)
static bool _send_data(gnrc_netif2_t *netif)
{
assert(gnrc_netdev != NULL);
assert(netif != NULL);
gnrc_pktsnip_t *pkt = gnrc_netdev->tx.packet;
gnrc_pktsnip_t *pkt = netif->mac.tx.packet;
gnrc_pktsnip_t *pkt_payload;
/* Enable Auto ACK again */
netopt_enable_t autoack = NETOPT_ENABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_AUTOACK,
&autoack, sizeof(autoack));
netif->dev->driver->set(netif->dev, NETOPT_AUTOACK,
&autoack, sizeof(autoack));
/* It's okay to retry sending DATA. Timing doesn't matter anymore and
* destination is waiting for a certain amount of time. */
uint8_t csma_retries = GNRC_LWMAC_DATA_CSMA_RETRIES;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_CSMA_RETRIES,
&csma_retries, sizeof(csma_retries));
netif->dev->driver->set(netif->dev, NETOPT_CSMA_RETRIES,
&csma_retries, sizeof(csma_retries));
gnrc_netdev->mac_info |= GNRC_NETDEV_MAC_INFO_CSMA_ENABLED;
netif->mac.mac_info |= GNRC_NETIF2_MAC_INFO_CSMA_ENABLED;
netopt_enable_t csma_enable = NETOPT_ENABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_CSMA,
&csma_enable, sizeof(csma_enable));
netif->dev->driver->set(netif->dev, NETOPT_CSMA,
&csma_enable, sizeof(csma_enable));
pkt_payload = pkt->next;
@ -403,198 +403,198 @@ static bool _send_data(gnrc_netdev_t *gnrc_netdev)
* In case the sender has no more packet for the receiver, it simply sets the
* data type to FRAMETYPE_DATA. */
gnrc_lwmac_hdr_t hdr;
if ((gnrc_priority_pktqueue_length(&gnrc_netdev->tx.current_neighbor->queue) > 0) &&
(gnrc_netdev->tx.tx_burst_count < GNRC_LWMAC_MAX_TX_BURST_PKT_NUM)) {
if ((gnrc_priority_pktqueue_length(&netif->mac.tx.current_neighbor->queue) > 0) &&
(netif->mac.tx.tx_burst_count < GNRC_LWMAC_MAX_TX_BURST_PKT_NUM)) {
hdr.type = GNRC_LWMAC_FRAMETYPE_DATA_PENDING;
gnrc_netdev_lwmac_set_tx_continue(gnrc_netdev, true);
gnrc_netdev->tx.tx_burst_count++;
gnrc_lwmac_set_tx_continue(netif, true);
netif->mac.tx.tx_burst_count++;
}
else {
hdr.type = GNRC_LWMAC_FRAMETYPE_DATA;
gnrc_netdev_lwmac_set_tx_continue(gnrc_netdev, false);
gnrc_lwmac_set_tx_continue(netif, false);
}
pkt->next = gnrc_pktbuf_add(pkt->next, &hdr, sizeof(hdr), GNRC_NETTYPE_LWMAC);
if (pkt->next == NULL) {
LOG_ERROR("ERROR: [LWMAC-tx] Cannot allocate pktbuf of type GNRC_NETTYPE_LWMAC\n");
LOG_ERROR("ERROR: [LWMAC-tx] Memory maybe full, drop the data packet\n");
gnrc_netdev->tx.packet->next = pkt_payload;
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
netif->mac.tx.packet->next = pkt_payload;
gnrc_pktbuf_release(netif->mac.tx.packet);
/* clear packet point to avoid TX retry */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
return false;
}
/* if found ongoing transmission, quit this cycle for collision avoidance.
* Data packet will be re-queued and try to send in the next cycle. */
if (_gnrc_lwmac_get_netdev_state(gnrc_netdev) == NETOPT_STATE_RX) {
if (_gnrc_lwmac_get_netdev_state(netif) == NETOPT_STATE_RX) {
/* save pointer to netif header */
gnrc_pktsnip_t *netif = pkt->next->next;
gnrc_pktsnip_t *netif_snip = pkt->next->next;
/* remove LWMAC header */
pkt->next->next = NULL;
gnrc_pktbuf_release(pkt->next);
/* make append netif header after payload again */
pkt->next = netif;
pkt->next = netif_snip;
if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, gnrc_netdev->tx.packet)) {
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
}
/* drop pointer so it wont be free'd */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
return false;
}
/* Send data */
int res = gnrc_netdev->send(gnrc_netdev, pkt);
int res = _gnrc_lwmac_transmit(netif, pkt);
if (res < 0) {
LOG_ERROR("ERROR: [LWMAC-tx] Send data failed.");
if (pkt != NULL) {
gnrc_pktbuf_release(pkt);
}
/* clear packet point to avoid TX retry */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
return false;
}
/* Packet has been released by netdev, so drop pointer */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
DEBUG("[LWMAC-tx]: spent %lu WR in TX\n", gnrc_netdev->tx.wr_sent);
DEBUG("[LWMAC-tx]: spent %lu WR in TX\n", netif->mac.tx.wr_sent);
#if (LWMAC_ENABLE_DUTYCYLE_RECORD == 1)
gnrc_netdev->lwmac.pkt_start_sending_time_ticks =
rtt_get_counter() - gnrc_netdev->lwmac.pkt_start_sending_time_ticks;
netif->mac.lwmac.pkt_start_sending_time_ticks =
rtt_get_counter() - netif->mac.lwmac.pkt_start_sending_time_ticks;
DEBUG("[LWMAC-tx]: pkt sending delay in TX: %lu us\n",
RTT_TICKS_TO_US(gnrc_netdev->lwmac.pkt_start_sending_time_ticks));
RTT_TICKS_TO_US(netif->mac.lwmac.pkt_start_sending_time_ticks));
#endif
return true;
}
void gnrc_lwmac_tx_start(gnrc_netdev_t *gnrc_netdev,
void gnrc_lwmac_tx_start(gnrc_netif2_t *netif,
gnrc_pktsnip_t *pkt,
gnrc_mac_tx_neighbor_t *neighbor)
{
assert(gnrc_netdev != NULL);
assert(netif != NULL);
assert(pkt != NULL);
assert(neighbor != NULL);
if (gnrc_netdev->tx.packet) {
if (netif->mac.tx.packet) {
LOG_WARNING("WARNING: [LWMAC-tx] Starting but tx.packet is still set\n");
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
gnrc_pktbuf_release(netif->mac.tx.packet);
}
gnrc_netdev->tx.packet = pkt;
gnrc_netdev->tx.current_neighbor = neighbor;
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_INIT;
gnrc_netdev->tx.wr_sent = 0;
netif->mac.tx.packet = pkt;
netif->mac.tx.current_neighbor = neighbor;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_INIT;
netif->mac.tx.wr_sent = 0;
#if (LWMAC_ENABLE_DUTYCYLE_RECORD == 1)
gnrc_netdev->lwmac.pkt_start_sending_time_ticks = rtt_get_counter();
netif->mac.lwmac.pkt_start_sending_time_ticks = rtt_get_counter();
#endif
}
void gnrc_lwmac_tx_stop(gnrc_netdev_t *gnrc_netdev)
void gnrc_lwmac_tx_stop(gnrc_netif2_t *netif)
{
assert(gnrc_netdev != NULL);
assert(netif != NULL);
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WR);
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NO_RESPONSE);
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST);
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_BROADCAST_END);
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_STOPPED;
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WR);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_BROADCAST_END);
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_STOPPED;
/* Release packet in case of failure */
if (gnrc_netdev->tx.packet) {
if (gnrc_netdev->tx.tx_retry_count >= GNRC_LWMAC_MAX_DATA_TX_RETRIES) {
gnrc_netdev->tx.tx_retry_count = 0;
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
gnrc_netdev->tx.packet = NULL;
if (netif->mac.tx.packet) {
if (netif->mac.tx.tx_retry_count >= GNRC_LWMAC_MAX_DATA_TX_RETRIES) {
netif->mac.tx.tx_retry_count = 0;
gnrc_pktbuf_release(netif->mac.tx.packet);
netif->mac.tx.packet = NULL;
LOG_WARNING("WARNING: [LWMAC-tx] Drop TX packet\n");
}
else {
gnrc_netdev->tx.tx_retry_count++;
netif->mac.tx.tx_retry_count++;
return;
}
}
if (!gnrc_netdev_lwmac_get_tx_continue(gnrc_netdev)) {
gnrc_netdev->tx.current_neighbor = NULL;
if (!gnrc_lwmac_get_tx_continue(netif)) {
netif->mac.tx.current_neighbor = NULL;
}
}
/* Returns whether rescheduling is needed or not */
static bool _lwmac_tx_update(gnrc_netdev_t *gnrc_netdev)
static bool _lwmac_tx_update(gnrc_netif2_t *netif)
{
assert(gnrc_netdev != NULL);
assert(netif != NULL);
bool reschedule = false;
switch (gnrc_netdev->tx.state) {
switch (netif->mac.tx.state) {
case GNRC_LWMAC_TX_STATE_INIT: {
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WR);
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NO_RESPONSE);
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST);
gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_BROADCAST_END);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WR);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_NEXT_BROADCAST);
gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_BROADCAST_END);
/* if found ongoing transmission,
* quit this cycle for collision avoidance. */
if (_gnrc_lwmac_get_netdev_state(gnrc_netdev) == NETOPT_STATE_RX) {
if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, gnrc_netdev->tx.packet)) {
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
if (_gnrc_lwmac_get_netdev_state(netif) == NETOPT_STATE_RX) {
if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
}
/* drop pointer so it wont be free'd */
gnrc_netdev->tx.packet = NULL;
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.packet = NULL;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
/* check if the packet is for broadcast */
if (gnrc_netif_hdr_get_flag(gnrc_netdev->tx.packet) &
if (gnrc_netif_hdr_get_flag(netif->mac.tx.packet) &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
/* Set CSMA retries as configured and enable */
uint8_t csma_retries = GNRC_LWMAC_BROADCAST_CSMA_RETRIES;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_CSMA_RETRIES,
&csma_retries, sizeof(csma_retries));
gnrc_netdev->mac_info |= GNRC_NETDEV_MAC_INFO_CSMA_ENABLED;
netif->dev->driver->set(netif->dev, NETOPT_CSMA_RETRIES,
&csma_retries, sizeof(csma_retries));
netif->mac.mac_info |= GNRC_NETIF2_MAC_INFO_CSMA_ENABLED;
netopt_enable_t csma_enable = NETOPT_ENABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_CSMA,
&csma_enable, sizeof(csma_enable));
netif->dev->driver->set(netif->dev, NETOPT_CSMA,
&csma_enable, sizeof(csma_enable));
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_SEND_BROADCAST;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SEND_BROADCAST;
reschedule = true;
break;
}
else {
/* Use CSMA for the first WR */
gnrc_netdev->mac_info |= GNRC_NETDEV_MAC_INFO_CSMA_ENABLED;
netif->mac.mac_info |= GNRC_NETIF2_MAC_INFO_CSMA_ENABLED;
netopt_enable_t csma_disable = NETOPT_ENABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_CSMA,
&csma_disable, sizeof(csma_disable));
netif->dev->driver->set(netif->dev, NETOPT_CSMA,
&csma_disable, sizeof(csma_disable));
/* Set a timeout for the maximum transmission procedure */
gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NO_RESPONSE, GNRC_LWMAC_PREAMBLE_DURATION_US);
gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE, GNRC_LWMAC_PREAMBLE_DURATION_US);
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_SEND_WR;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SEND_WR;
reschedule = true;
break;
}
}
case GNRC_LWMAC_TX_STATE_SEND_BROADCAST: {
uint8_t tx_info = _send_bcast(gnrc_netdev);
uint8_t tx_info = _send_bcast(netif);
if (tx_info & GNRC_LWMAC_TX_SUCCESS) {
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_SUCCESSFUL;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SUCCESSFUL;
reschedule = true;
break;
}
if (tx_info & GNRC_LWMAC_TX_FAIL) {
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
@ -603,23 +603,23 @@ static bool _lwmac_tx_update(gnrc_netdev_t *gnrc_netdev)
}
case GNRC_LWMAC_TX_STATE_SEND_WR: {
/* In case of no Tx-isr error (e.g., no Tx-isr), goto TX failure. */
if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) {
if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) {
LOG_WARNING("WARNING: [LWMAC-tx] No response from destination, "
"probably no TX-ISR\n");
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
"probably no TX-ISR\n");
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
LOG_DEBUG("[LWMAC-tx] GNRC_LWMAC_TX_STATE_SEND_WR\n");
uint8_t tx_info = _send_wr(gnrc_netdev);
uint8_t tx_info = _send_wr(netif);
if (tx_info & GNRC_LWMAC_TX_FAIL) {
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_WAIT_WR_SENT;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_WAIT_WR_SENT;
reschedule = false;
break;
}
@ -627,84 +627,84 @@ static bool _lwmac_tx_update(gnrc_netdev_t *gnrc_netdev)
LOG_DEBUG("[LWMAC-tx] GNRC_LWMAC_TX_STATE_WAIT_WR_SENT\n");
/* In case of no Tx-isr error (e.g., no Tx-isr), goto TX failure. */
if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) {
if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) {
LOG_WARNING("WARNING: [LWMAC-tx] No response from destination\n");
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
if (gnrc_netdev_get_tx_feedback(gnrc_netdev) == TX_FEEDBACK_UNDEF) {
if (gnrc_netif2_get_tx_feedback(netif) == TX_FEEDBACK_UNDEF) {
LOG_DEBUG("[LWMAC-tx] WR not yet completely sent\n");
break;
}
/* If found ongoing transmission, goto TX failure, i.e., postpone transmission to
* next cycle. This is mainly for collision avoidance. */
if (gnrc_netdev_get_tx_feedback(gnrc_netdev) == TX_FEEDBACK_BUSY) {
if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, gnrc_netdev->tx.packet)) {
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
if (gnrc_netif2_get_tx_feedback(netif) == TX_FEEDBACK_BUSY) {
if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
}
/* clear packet point to avoid TX retry */
gnrc_netdev->tx.packet = NULL;
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.packet = NULL;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
if (gnrc_netdev->tx.wr_sent == 0) {
if (netif->mac.tx.wr_sent == 0) {
/* Only the first WR use CSMA */
gnrc_netdev->mac_info &= ~GNRC_NETDEV_MAC_INFO_CSMA_ENABLED;
netif->mac.mac_info &= ~GNRC_NETIF2_MAC_INFO_CSMA_ENABLED;
netopt_enable_t csma_disable = NETOPT_DISABLE;
gnrc_netdev->dev->driver->set(gnrc_netdev->dev, NETOPT_CSMA,
&csma_disable, sizeof(csma_disable));
netif->dev->driver->set(netif->dev, NETOPT_CSMA,
&csma_disable, sizeof(csma_disable));
}
gnrc_netdev->tx.wr_sent++;
netif->mac.tx.wr_sent++;
/* Set timeout for next WR in case no WA will be received */
gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WR, GNRC_LWMAC_TIME_BETWEEN_WR_US);
gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_WR, GNRC_LWMAC_TIME_BETWEEN_WR_US);
/* Debug WR timing */
LOG_DEBUG("[LWMAC-tx] Destination phase was: %" PRIu32 "\n",
gnrc_netdev->tx.current_neighbor->phase);
netif->mac.tx.current_neighbor->phase);
LOG_DEBUG("[LWMAC-tx] Phase when sent was: %" PRIu32 "\n",
_gnrc_lwmac_ticks_to_phase(gnrc_netdev->tx.timestamp));
_gnrc_lwmac_ticks_to_phase(netif->mac.tx.timestamp));
LOG_DEBUG("[LWMAC-tx] Ticks when sent was: %" PRIu32 "\n",
gnrc_netdev->tx.timestamp);
_gnrc_lwmac_set_netdev_state(gnrc_netdev, NETOPT_STATE_IDLE);
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_WAIT_FOR_WA;
netif->mac.tx.timestamp);
_gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE);
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_WAIT_FOR_WA;
reschedule = false;
break;
}
case GNRC_LWMAC_TX_STATE_WAIT_FOR_WA: {
LOG_DEBUG("[LWMAC-tx] GNRC_LWMAC_TX_STATE_WAIT_FOR_WA\n");
if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) {
if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) {
LOG_WARNING("WARNING: [LWMAC-tx] No response from destination\n");
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WR)) {
if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_WR)) {
/* In case the sender is in consecutive (burst) transmission to the receiver,
* meaning that the sender has already successfully sent at least one data to
* the receiver, then the sender will only spend one WR for triggering the next
* transmission procedure. And, if this WR doesn't work (no WA replied), the
* sender regards consecutive transmission failed.
*/
if (gnrc_netdev_lwmac_get_tx_continue(gnrc_netdev)) {
if (gnrc_lwmac_get_tx_continue(netif)) {
LOG_DEBUG("[LWMAC-tx] Tx burst fail\n");
if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, gnrc_netdev->tx.packet)) {
gnrc_pktbuf_release(gnrc_netdev->tx.packet);
if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, netif->mac.tx.packet)) {
gnrc_pktbuf_release(netif->mac.tx.packet);
LOG_WARNING("WARNING: [LWMAC-tx] TX queue full, drop packet\n");
}
/* drop pointer so it wont be free'd */
gnrc_netdev->tx.packet = NULL;
netif->mac.tx.packet = NULL;
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
@ -713,27 +713,27 @@ static bool _lwmac_tx_update(gnrc_netdev_t *gnrc_netdev)
* latter's wake-up period, the sender just keep sending WRs until it
* finds the WA.
*/
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_SEND_WR;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SEND_WR;
reschedule = true;
break;
}
}
if (_gnrc_lwmac_get_netdev_state(gnrc_netdev) == NETOPT_STATE_RX) {
if (_gnrc_lwmac_get_netdev_state(netif) == NETOPT_STATE_RX) {
/* Wait for completion of frame reception */
break;
}
uint8_t tx_info = _packet_process_in_wait_for_wa(gnrc_netdev);
uint8_t tx_info = _packet_process_in_wait_for_wa(netif);
if (tx_info & GNRC_LWMAC_TX_FAIL) {
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
if (tx_info & GNRC_LWMAC_TX_SUCCESS) {
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_SEND_DATA;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SEND_DATA;
reschedule = true;
break;
}
@ -745,49 +745,49 @@ static bool _lwmac_tx_update(gnrc_netdev_t *gnrc_netdev)
case GNRC_LWMAC_TX_STATE_SEND_DATA: {
LOG_DEBUG("[LWMAC-tx] GNRC_LWMAC_TX_STATE_SEND_DATA\n");
if (!_send_data(gnrc_netdev)) {
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
if (!_send_data(netif)) {
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_WAIT_FEEDBACK;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_WAIT_FEEDBACK;
reschedule = false;
break;
}
case GNRC_LWMAC_TX_STATE_WAIT_FEEDBACK: {
/* In case of no Tx-isr error, goto TX failure. */
if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) {
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) {
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
LOG_DEBUG("[LWMAC-tx] GNRC_LWMAC_TX_STATE_WAIT_FEEDBACK\n");
if (gnrc_netdev_get_tx_feedback(gnrc_netdev) == TX_FEEDBACK_UNDEF) {
if (gnrc_netif2_get_tx_feedback(netif) == TX_FEEDBACK_UNDEF) {
break;
}
else if (gnrc_netdev_get_tx_feedback(gnrc_netdev) == TX_FEEDBACK_SUCCESS) {
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_SUCCESSFUL;
else if (gnrc_netif2_get_tx_feedback(netif) == TX_FEEDBACK_SUCCESS) {
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SUCCESSFUL;
reschedule = true;
break;
}
else if (gnrc_netdev_get_tx_feedback(gnrc_netdev) == TX_FEEDBACK_NOACK) {
else if (gnrc_netif2_get_tx_feedback(netif) == TX_FEEDBACK_NOACK) {
LOG_ERROR("ERROR: [LWMAC-tx] Not ACKED\n");
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
else if (gnrc_netdev_get_tx_feedback(gnrc_netdev) == TX_FEEDBACK_BUSY) {
else if (gnrc_netif2_get_tx_feedback(netif) == TX_FEEDBACK_BUSY) {
LOG_ERROR("ERROR: [LWMAC-tx] Channel busy \n");
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
LOG_ERROR("ERROR: [LWMAC-tx] Tx feedback unhandled: %i\n",
gnrc_netdev_get_tx_feedback(gnrc_netdev));
gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_FAILED;
gnrc_netif2_get_tx_feedback(netif));
netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED;
reschedule = true;
break;
}
@ -803,8 +803,8 @@ static bool _lwmac_tx_update(gnrc_netdev_t *gnrc_netdev)
return reschedule;
}
void gnrc_lwmac_tx_update(gnrc_netdev_t *gnrc_netdev)
void gnrc_lwmac_tx_update(gnrc_netif2_t *netif)
{
/* Update until no rescheduling needed */
while (_lwmac_tx_update(gnrc_netdev)) {}
while (_lwmac_tx_update(netif)) {}
}

View File

@ -223,8 +223,8 @@ static int _send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt)
}
#endif
#ifdef MODULE_GNRC_MAC
if (netif->mac_info & GNRC_NETDEV_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, vector, n, &netif->csma_conf);
if (netif->mac.mac_info & GNRC_NETIF2_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, vector, n, &netif->mac.csma_conf);
}
else {
res = dev->driver->send(dev, vector, n);