From c554d30b268fbc92cc2017c56ec0537962c59249 Mon Sep 17 00:00:00 2001 From: zhuoshuguo <shuguo.zhuo@inria.fr> Date: Thu, 19 Oct 2017 19:40:58 +0200 Subject: [PATCH] gnrc_lwmac: port to gnrc_netif2. --- Makefile.dep | 2 +- sys/auto_init/netif/auto_init_at86rf2xx.c | 15 +- sys/include/net/gnrc/lwmac/hdr.h | 18 +- sys/include/net/gnrc/lwmac/lwmac.h | 38 +- sys/include/net/gnrc/lwmac/timeout.h | 22 +- sys/include/net/gnrc/lwmac/types.h | 92 +-- sys/include/net/gnrc/mac/internal.h | 65 ++ sys/include/net/gnrc/netif2/mac.h | 38 + .../link_layer/lwmac/include/lwmac_internal.h | 172 ++-- .../lwmac/include/rx_state_machine.h | 14 +- .../lwmac/include/tx_state_machine.h | 14 +- sys/net/gnrc/link_layer/lwmac/lwmac.c | 759 +++++++++--------- .../gnrc/link_layer/lwmac/lwmac_internal.c | 159 +++- .../gnrc/link_layer/lwmac/rx_state_machine.c | 178 ++-- sys/net/gnrc/link_layer/lwmac/timeout.c | 54 +- .../gnrc/link_layer/lwmac/tx_state_machine.c | 420 +++++----- sys/net/gnrc/netif2/gnrc_netif2_ieee802154.c | 4 +- 17 files changed, 1149 insertions(+), 915 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index 86dbc62bd9..342a8aa204 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -549,8 +549,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 diff --git a/sys/auto_init/netif/auto_init_at86rf2xx.c b/sys/auto_init/netif/auto_init_at86rf2xx.c index e49d355faa..803e317665 100644 --- a/sys/auto_init/netif/auto_init_at86rf2xx.c +++ b/sys/auto_init/netif/auto_init_at86rf2xx.c @@ -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 } diff --git a/sys/include/net/gnrc/lwmac/hdr.h b/sys/include/net/gnrc/lwmac/hdr.h index 08fd018a3f..b599604bdc 100644 --- a/sys/include/net/gnrc/lwmac/hdr.h +++ b/sys/include/net/gnrc/lwmac/hdr.h @@ -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; /** diff --git a/sys/include/net/gnrc/lwmac/lwmac.h b/sys/include/net/gnrc/lwmac/lwmac.h index b682da4c6e..081a6deb87 100644 --- a/sys/include/net/gnrc/lwmac/lwmac.h +++ b/sys/include/net/gnrc/lwmac/lwmac.h @@ -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 diff --git a/sys/include/net/gnrc/lwmac/timeout.h b/sys/include/net/gnrc/lwmac/timeout.h index 0a664b9dea..b3118e31bf 100644 --- a/sys/include/net/gnrc/lwmac/timeout.h +++ b/sys/include/net/gnrc/lwmac/timeout.h @@ -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. diff --git a/sys/include/net/gnrc/lwmac/types.h b/sys/include/net/gnrc/lwmac/types.h index 4d2e03815e..2185a4ee9b 100644 --- a/sys/include/net/gnrc/lwmac/types.h +++ b/sys/include/net/gnrc/lwmac/types.h @@ -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; diff --git a/sys/include/net/gnrc/mac/internal.h b/sys/include/net/gnrc/mac/internal.h index a9dd8924e3..3c7f8f64b9 100644 --- a/sys/include/net/gnrc/mac/internal.h +++ b/sys/include/net/gnrc/mac/internal.h @@ -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. diff --git a/sys/include/net/gnrc/netif2/mac.h b/sys/include/net/gnrc/netif2/mac.h index 8aed068f3f..08dc954253 100644 --- a/sys/include/net/gnrc/netif2/mac.h +++ b/sys/include/net/gnrc/netif2/mac.h @@ -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 diff --git a/sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h b/sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h index 88a5a1e397..7103c635a5 100644 --- a/sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h +++ b/sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h @@ -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 diff --git a/sys/net/gnrc/link_layer/lwmac/include/rx_state_machine.h b/sys/net/gnrc/link_layer/lwmac/include/rx_state_machine.h index 4d585e0dad..f045e19133 100644 --- a/sys/net/gnrc/link_layer/lwmac/include/rx_state_machine.h +++ b/sys/net/gnrc/link_layer/lwmac/include/rx_state_machine.h @@ -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 } diff --git a/sys/net/gnrc/link_layer/lwmac/include/tx_state_machine.h b/sys/net/gnrc/link_layer/lwmac/include/tx_state_machine.h index 4787c23444..f8da8bdc98 100644 --- a/sys/net/gnrc/link_layer/lwmac/include/tx_state_machine.h +++ b/sys/net/gnrc/link_layer/lwmac/include/tx_state_machine.h @@ -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 } diff --git a/sys/net/gnrc/link_layer/lwmac/lwmac.c b/sys/net/gnrc/link_layer/lwmac/lwmac.c index db855afcc1..d9627a0e79 100644 --- a/sys/net/gnrc/link_layer/lwmac/lwmac.c +++ b/sys/net/gnrc/link_layer/lwmac/lwmac.c @@ -25,15 +25,13 @@ #include <stdint.h> #include <stdbool.h> -#include "kernel_types.h" -#include "msg.h" -#include "thread.h" #include "timex.h" #include "random.h" #include "periph/rtt.h" -#include "net/gnrc.h" -#include "net/netdev.h" -#include "net/gnrc/netdev.h" +#include "net/gnrc/netif2.h" +#include "net/gnrc/netif2/internal.h" +#include "net/gnrc/netif2/ieee802154.h" +#include "net/netdev/ieee802154.h" #include "net/gnrc/lwmac/types.h" #include "net/gnrc/lwmac/lwmac.h" #include "net/gnrc/mac/internal.h" @@ -60,22 +58,156 @@ kernel_pid_t lwmac_pid; static void rtt_cb(void *arg); -static void lwmac_set_state(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_state_t newstate); -static void lwmac_schedule_update(gnrc_netdev_t *gnrc_netdev); -static void rtt_handler(uint32_t event, gnrc_netdev_t *gnrc_netdev); +static void lwmac_set_state(gnrc_netif2_t *netif, gnrc_lwmac_state_t newstate); +static void lwmac_schedule_update(gnrc_netif2_t *netif); +static void rtt_handler(uint32_t event, gnrc_netif2_t *netif); +static void _lwmac_init(gnrc_netif2_t *netif); +static int _send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt); +static gnrc_pktsnip_t *_recv(gnrc_netif2_t *netif); +static void _lwmac_msg_handler(gnrc_netif2_t *netif, msg_t *msg); + +static const gnrc_netif2_ops_t lwmac_ops = { + .init = _lwmac_init, + .send = _send, + .recv = _recv, + .get = gnrc_netif2_get_from_netdev, + .set = gnrc_netif2_set_from_netdev, + .msg_handler = _lwmac_msg_handler, +}; + +gnrc_netif2_t *gnrc_netif2_lwmac_create(char *stack, int stacksize, + char priority, char *name, + netdev_t *dev) +{ + return gnrc_netif2_create(stack, stacksize, priority, name, dev, + &lwmac_ops); +} + +static gnrc_pktsnip_t *_make_netif_hdr(uint8_t *mhr) +{ + gnrc_pktsnip_t *snip; + uint8_t src[IEEE802154_LONG_ADDRESS_LEN], dst[IEEE802154_LONG_ADDRESS_LEN]; + int src_len, dst_len; + le_uint16_t _pan_tmp; /* TODO: hand-up PAN IDs to GNRC? */ + + dst_len = ieee802154_get_dst(mhr, dst, &_pan_tmp); + src_len = ieee802154_get_src(mhr, src, &_pan_tmp); + if ((dst_len < 0) || (src_len < 0)) { + DEBUG("_make_netif_hdr: unable to get addresses\n"); + return NULL; + } + /* allocate space for header */ + snip = gnrc_netif_hdr_build(src, (size_t)src_len, dst, (size_t)dst_len); + if (snip == NULL) { + DEBUG("_make_netif_hdr: no space left in packet buffer\n"); + return NULL; + } + /* set broadcast flag for broadcast destination */ + if ((dst_len == 2) && (dst[0] == 0xff) && (dst[1] == 0xff)) { + gnrc_netif_hdr_t *hdr = snip->data; + hdr->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; + } + return snip; +} + +static gnrc_pktsnip_t *_recv(gnrc_netif2_t *netif) +{ + netdev_t *dev = netif->dev; + netdev_ieee802154_rx_info_t rx_info; + netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev; + gnrc_pktsnip_t *pkt = NULL; + int bytes_expected = dev->driver->recv(dev, NULL, 0, NULL); + + if (bytes_expected > 0) { + int nread; + + pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF); + if (pkt == NULL) { + DEBUG("_recv_ieee802154: cannot allocate pktsnip.\n"); + return NULL; + } + nread = dev->driver->recv(dev, pkt->data, bytes_expected, &rx_info); + if (nread <= 0) { + gnrc_pktbuf_release(pkt); + return NULL; + } + if (!(state->flags & NETDEV_IEEE802154_RAW)) { + gnrc_pktsnip_t *ieee802154_hdr, *netif_hdr; + gnrc_netif_hdr_t *hdr; +#if ENABLE_DEBUG + char src_str[GNRC_NETIF_HDR_L2ADDR_PRINT_LEN]; +#endif + size_t mhr_len = ieee802154_get_frame_hdr_len(pkt->data); + + if (mhr_len == 0) { + DEBUG("_recv_ieee802154: illegally formatted frame received\n"); + gnrc_pktbuf_release(pkt); + return NULL; + } + nread -= mhr_len; + /* mark IEEE 802.15.4 header */ + ieee802154_hdr = gnrc_pktbuf_mark(pkt, mhr_len, GNRC_NETTYPE_UNDEF); + if (ieee802154_hdr == NULL) { + DEBUG("_recv_ieee802154: no space left in packet buffer\n"); + gnrc_pktbuf_release(pkt); + return NULL; + } + netif_hdr = _make_netif_hdr(ieee802154_hdr->data); + if (netif_hdr == NULL) { + DEBUG("_recv_ieee802154: no space left in packet buffer\n"); + gnrc_pktbuf_release(pkt); + return NULL; + } + + hdr = netif_hdr->data; + +#ifdef MODULE_L2FILTER + if (!l2filter_pass(dev->filter, gnrc_netif_hdr_get_src_addr(hdr), + hdr->src_l2addr_len)) { + gnrc_pktbuf_release(pkt); + gnrc_pktbuf_release(netif_hdr); + DEBUG("_recv_ieee802154: packet dropped by l2filter\n"); + return NULL; + } +#endif + + hdr->lqi = rx_info.lqi; + hdr->rssi = rx_info.rssi; + hdr->if_pid = thread_getpid(); + pkt->type = state->proto; +#if ENABLE_DEBUG + DEBUG("_recv_ieee802154: received packet from %s of length %u\n", + gnrc_netif_addr_to_str(src_str, sizeof(src_str), + gnrc_netif_hdr_get_src_addr(hdr), + hdr->src_l2addr_len), + nread); +#if defined(MODULE_OD) + od_hex_dump(pkt->data, nread, OD_WIDTH_DEFAULT); +#endif +#endif + gnrc_pktbuf_remove_snip(pkt, ieee802154_hdr); + LL_APPEND(pkt, netif_hdr); + } + + DEBUG("_recv_ieee802154: reallocating.\n"); + gnrc_pktbuf_realloc_data(pkt, nread); + } + + return pkt; +} -static gnrc_mac_tx_neighbor_t *_next_tx_neighbor(gnrc_netdev_t *gnrc_netdev) +static gnrc_mac_tx_neighbor_t *_next_tx_neighbor(gnrc_netif2_t *netif) { int next = -1; uint32_t phase_nearest = GNRC_LWMAC_PHASE_MAX; for (int i = 0; i < GNRC_MAC_NEIGHBOR_COUNT; i++) { - if (gnrc_priority_pktqueue_length(&gnrc_netdev->tx.neighbors[i].queue) > 0) { + if (gnrc_priority_pktqueue_length(&netif->mac.tx.neighbors[i].queue) > 0) { /* Unknown destinations are initialized with their phase at the end * of the local interval, so known destinations that still wakeup * in this interval will be preferred. */ - uint32_t phase_check = _gnrc_lwmac_ticks_until_phase(gnrc_netdev->tx.neighbors[i].phase); + uint32_t phase_check = _gnrc_lwmac_ticks_until_phase(netif->mac.tx.neighbors[i].phase); if (phase_check <= phase_nearest) { next = i; @@ -85,7 +217,7 @@ static gnrc_mac_tx_neighbor_t *_next_tx_neighbor(gnrc_netdev_t *gnrc_netdev) } } - return (next < 0) ? NULL : &(gnrc_netdev->tx.neighbors[next]); + return (next < 0) ? NULL : &(netif->mac.tx.neighbors[next]); } static uint32_t _next_inphase_event(uint32_t last, uint32_t interval) @@ -107,14 +239,14 @@ static uint32_t _next_inphase_event(uint32_t last, uint32_t interval) return last; } -inline void lwmac_schedule_update(gnrc_netdev_t *gnrc_netdev) +inline void lwmac_schedule_update(gnrc_netif2_t *netif) { - gnrc_netdev_lwmac_set_reschedule(gnrc_netdev, true); + gnrc_lwmac_set_reschedule(netif, true); } -void lwmac_set_state(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_state_t newstate) +void lwmac_set_state(gnrc_netif2_t *netif, gnrc_lwmac_state_t newstate) { - gnrc_lwmac_state_t oldstate = gnrc_netdev->lwmac.state; + gnrc_lwmac_state_t oldstate = netif->mac.lwmac.state; if (newstate == oldstate) { return; @@ -126,26 +258,26 @@ void lwmac_set_state(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_state_t newstate) } /* Already change state, but might be reverted to oldstate when needed */ - gnrc_netdev->lwmac.state = newstate; + netif->mac.lwmac.state = newstate; /* Actions when leaving old state */ switch (oldstate) { case GNRC_LWMAC_RECEIVING: case GNRC_LWMAC_TRANSMITTING: { /* Enable duty cycling again */ - rtt_handler(GNRC_LWMAC_EVENT_RTT_RESUME, gnrc_netdev); + rtt_handler(GNRC_LWMAC_EVENT_RTT_RESUME, netif); #if (GNRC_LWMAC_ENABLE_DUTYCYLE_RECORD == 1) /* Output duty-cycle ratio */ uint64_t duty; duty = (uint64_t) rtt_get_counter(); - duty = ((uint64_t) gnrc_netdev->lwmac.awake_duration_sum_ticks) * 100 / - (duty - (uint64_t)gnrc_netdev->lwmac.system_start_time_ticks); + duty = ((uint64_t) netif->mac.lwmac.awake_duration_sum_ticks) * 100 / + (duty - (uint64_t)netif->mac.lwmac.system_start_time_ticks); printf("[LWMAC]: achieved duty-cycle: %lu %% \n", (uint32_t)duty); #endif break; } case GNRC_LWMAC_SLEEPING: { - gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); + gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); break; } default: @@ -156,17 +288,17 @@ void lwmac_set_state(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_state_t newstate) switch (newstate) { /*********************** Operation states *********************************/ case GNRC_LWMAC_LISTENING: { - _gnrc_lwmac_set_netdev_state(gnrc_netdev, NETOPT_STATE_IDLE); + _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE); break; } case GNRC_LWMAC_SLEEPING: { /* Put transceiver to sleep */ - _gnrc_lwmac_set_netdev_state(gnrc_netdev, NETOPT_STATE_SLEEP); + _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_SLEEP); /* We may have come here through RTT handler, so timeout may still be active */ - gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); + gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); - if (gnrc_netdev_lwmac_get_phase_backoff(gnrc_netdev)) { - gnrc_netdev_lwmac_set_phase_backoff(gnrc_netdev, false); + if (gnrc_lwmac_get_phase_backoff(netif)) { + gnrc_lwmac_set_phase_backoff(netif, false); uint32_t alarm; rtt_clear_alarm(); @@ -174,8 +306,8 @@ void lwmac_set_state(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_state_t newstate) RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US - (3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2))); LOG_WARNING("WARNING: [LWMAC] phase backoffed: %lu us\n", RTT_TICKS_TO_US(alarm)); - gnrc_netdev->lwmac.last_wakeup = gnrc_netdev->lwmac.last_wakeup + alarm; - alarm = _next_inphase_event(gnrc_netdev->lwmac.last_wakeup, + netif->mac.lwmac.last_wakeup = netif->mac.lwmac.last_wakeup + alarm; + alarm = _next_inphase_event(netif->mac.lwmac.last_wakeup, RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); } @@ -185,35 +317,35 @@ void lwmac_set_state(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_state_t newstate) } /* Trying to send data */ case GNRC_LWMAC_TRANSMITTING: { - rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, gnrc_netdev); /**< No duty cycling while RXing */ - _gnrc_lwmac_set_netdev_state(gnrc_netdev, NETOPT_STATE_IDLE); /**< Power up netdev */ + rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, netif); /**< No duty cycling while RXing */ + _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE); /**< Power up netdev */ break; } /* Receiving incoming data */ case GNRC_LWMAC_RECEIVING: { - rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, gnrc_netdev); /**< No duty cycling while TXing */ - _gnrc_lwmac_set_netdev_state(gnrc_netdev, NETOPT_STATE_IDLE); /**< Power up netdev */ + rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, netif); /**< No duty cycling while TXing */ + _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE); /**< Power up netdev */ break; } case GNRC_LWMAC_STOPPED: { - _gnrc_lwmac_set_netdev_state(gnrc_netdev, NETOPT_STATE_OFF); + _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_OFF); break; } /*********************** Control states ***********************************/ case GNRC_LWMAC_START: { - rtt_handler(GNRC_LWMAC_EVENT_RTT_START, gnrc_netdev); - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_LISTENING); + rtt_handler(GNRC_LWMAC_EVENT_RTT_START, netif); + lwmac_set_state(netif, GNRC_LWMAC_LISTENING); break; } case GNRC_LWMAC_STOP: { - rtt_handler(GNRC_LWMAC_EVENT_RTT_STOP, gnrc_netdev); - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_STOPPED); + rtt_handler(GNRC_LWMAC_EVENT_RTT_STOP, netif); + lwmac_set_state(netif, GNRC_LWMAC_STOPPED); break; } case GNRC_LWMAC_RESET: { LOG_WARNING("WARNING: [LWMAC] Reset not yet implemented\n"); - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_STOP); - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_START); + lwmac_set_state(netif, GNRC_LWMAC_STOP); + lwmac_set_state(netif, GNRC_LWMAC_START); break; } /**************************************************************************/ @@ -223,38 +355,38 @@ void lwmac_set_state(gnrc_netdev_t *gnrc_netdev, gnrc_lwmac_state_t newstate) } } - lwmac_schedule_update(gnrc_netdev); + lwmac_schedule_update(netif); } -static void _sleep_management(gnrc_netdev_t *gnrc_netdev) +static void _sleep_management(gnrc_netif2_t *netif) { /* If a packet is scheduled, no other (possible earlier) packet can be * sent before the first one is handled, even no broadcast */ - if (!gnrc_lwmac_timeout_is_running(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP)) { + if (!gnrc_lwmac_timeout_is_running(netif, GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP)) { gnrc_mac_tx_neighbor_t *neighbour; /* Check if there is packet remaining for retransmission */ - if (gnrc_netdev->tx.current_neighbor != NULL) { - neighbour = gnrc_netdev->tx.current_neighbor; + if (netif->mac.tx.current_neighbor != NULL) { + neighbour = netif->mac.tx.current_neighbor; } else { /* Check if there are broadcasts to send and transmit immediately */ - if (gnrc_priority_pktqueue_length(&(gnrc_netdev->tx.neighbors[0].queue)) > 0) { - gnrc_netdev->tx.current_neighbor = &(gnrc_netdev->tx.neighbors[0]); - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_TRANSMITTING); + if (gnrc_priority_pktqueue_length(&(netif->mac.tx.neighbors[0].queue)) > 0) { + netif->mac.tx.current_neighbor = &(netif->mac.tx.neighbors[0]); + lwmac_set_state(netif, GNRC_LWMAC_TRANSMITTING); return; } - neighbour = _next_tx_neighbor(gnrc_netdev); + neighbour = _next_tx_neighbor(netif); } if (neighbour != NULL) { /* if phase is unknown, send immediately. */ if (neighbour->phase > RTT_TICKS_TO_US(GNRC_LWMAC_WAKEUP_INTERVAL_US)) { - gnrc_netdev->tx.current_neighbor = neighbour; - gnrc_netdev_lwmac_set_tx_continue(gnrc_netdev, false); - gnrc_netdev->tx.tx_burst_count = 0; - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_TRANSMITTING); + netif->mac.tx.current_neighbor = neighbour; + gnrc_lwmac_set_tx_continue(netif, false); + netif->mac.tx.tx_burst_count = 0; + lwmac_set_state(netif, GNRC_LWMAC_TRANSMITTING); return; } @@ -276,275 +408,276 @@ static void _sleep_management(gnrc_netdev_t *gnrc_netdev) random_backoff = random_uint32_range(0, GNRC_LWMAC_TIME_BETWEEN_WR_US); time_until_tx = time_until_tx + random_backoff; - gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP, time_until_tx); + gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP, time_until_tx); /* Register neighbour to be the next */ - gnrc_netdev->tx.current_neighbor = neighbour; + netif->mac.tx.current_neighbor = neighbour; /* Stop dutycycling, we're preparing to send. This prevents the * timeout arriving late, so that the destination phase would * be missed. */ /* TODO: bad for power savings */ - rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, gnrc_netdev); + rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, netif); } } - else if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP)) { + else if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP)) { LOG_DEBUG("[LWMAC] Got timeout for dest wakeup, ticks: %" PRIu32 "\n", rtt_get_counter()); - gnrc_netdev_lwmac_set_tx_continue(gnrc_netdev, false); - gnrc_netdev->tx.tx_burst_count = 0; - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_TRANSMITTING); + gnrc_lwmac_set_tx_continue(netif, false); + netif->mac.tx.tx_burst_count = 0; + lwmac_set_state(netif, GNRC_LWMAC_TRANSMITTING); } } -static void _rx_management_failed(gnrc_netdev_t *gnrc_netdev) +static void _rx_management_failed(gnrc_netif2_t *netif) { /* This may happen frequently because we'll receive WA from * every node in range. */ LOG_DEBUG("[LWMAC] Reception was NOT successful\n"); - gnrc_lwmac_rx_stop(gnrc_netdev); + gnrc_lwmac_rx_stop(netif); - if (gnrc_netdev->rx.rx_bad_exten_count >= GNRC_LWMAC_MAX_RX_EXTENSION_NUM) { - gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true); + if (netif->mac.rx.rx_bad_exten_count >= GNRC_LWMAC_MAX_RX_EXTENSION_NUM) { + gnrc_lwmac_set_quit_rx(netif, true); } /* Here we check if we are close to the end of the cycle. If yes, * go to sleep. Firstly, get the relative phase. */ uint32_t phase = rtt_get_counter(); - if (phase < gnrc_netdev->lwmac.last_wakeup) { - phase = (RTT_US_TO_TICKS(GNRC_LWMAC_PHASE_MAX) - gnrc_netdev->lwmac.last_wakeup) + - phase; + if (phase < netif->mac.lwmac.last_wakeup) { + phase = (RTT_US_TO_TICKS(GNRC_LWMAC_PHASE_MAX) - netif->mac.lwmac.last_wakeup) + + phase; } else { - phase = phase - gnrc_netdev->lwmac.last_wakeup; + phase = phase - netif->mac.lwmac.last_wakeup; } /* If the relative phase is beyond 4/5 cycle time, go to sleep. */ - if (phase > (4*RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)/5)) { - gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true); + if (phase > (4 * RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US) / 5)) { + gnrc_lwmac_set_quit_rx(netif, true); } - if (gnrc_netdev_lwmac_get_quit_rx(gnrc_netdev)) { - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_SLEEPING); + if (gnrc_lwmac_get_quit_rx(netif)) { + lwmac_set_state(netif, GNRC_LWMAC_SLEEPING); } else { /* Go back to LISTENING for keep hearing on the channel */ - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_LISTENING); + lwmac_set_state(netif, GNRC_LWMAC_LISTENING); } } -static void _rx_management_success(gnrc_netdev_t *gnrc_netdev) +static void _rx_management_success(gnrc_netif2_t *netif) { LOG_DEBUG("[LWMAC] Reception was successful\n"); - gnrc_lwmac_rx_stop(gnrc_netdev); + gnrc_lwmac_rx_stop(netif); /* Dispatch received packets, timing is not critical anymore */ - gnrc_mac_dispatch(&gnrc_netdev->rx); + gnrc_mac_dispatch(&netif->mac.rx); /* Here we check if we are close to the end of the cycle. If yes, * go to sleep. Firstly, get the relative phase. */ uint32_t phase = rtt_get_counter(); - if (phase < gnrc_netdev->lwmac.last_wakeup) { - phase = (RTT_US_TO_TICKS(GNRC_LWMAC_PHASE_MAX) - gnrc_netdev->lwmac.last_wakeup) + - phase; + if (phase < netif->mac.lwmac.last_wakeup) { + phase = (RTT_US_TO_TICKS(GNRC_LWMAC_PHASE_MAX) - netif->mac.lwmac.last_wakeup) + + phase; } else { - phase = phase - gnrc_netdev->lwmac.last_wakeup; + phase = phase - netif->mac.lwmac.last_wakeup; } /* If the relative phase is beyond 4/5 cycle time, go to sleep. */ - if (phase > (4*RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)/5)) { - gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, true); + if (phase > (4 * RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US) / 5)) { + gnrc_lwmac_set_quit_rx(netif, true); } - if (gnrc_netdev_lwmac_get_quit_rx(gnrc_netdev)) { - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_SLEEPING); + if (gnrc_lwmac_get_quit_rx(netif)) { + lwmac_set_state(netif, GNRC_LWMAC_SLEEPING); } else { /* Go back to LISTENING after successful reception */ - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_LISTENING); + lwmac_set_state(netif, GNRC_LWMAC_LISTENING); } } -static void _rx_management(gnrc_netdev_t *gnrc_netdev) + +static void _rx_management(gnrc_netif2_t *netif) { - gnrc_lwmac_rx_state_t state_rx = gnrc_netdev->rx.state; + gnrc_lwmac_rx_state_t state_rx = netif->mac.rx.state; switch (state_rx) { case GNRC_LWMAC_RX_STATE_STOPPED: { - gnrc_lwmac_rx_start(gnrc_netdev); - gnrc_lwmac_rx_update(gnrc_netdev); + gnrc_lwmac_rx_start(netif); + gnrc_lwmac_rx_update(netif); break; } case GNRC_LWMAC_RX_STATE_FAILED: { - _rx_management_failed(gnrc_netdev); + _rx_management_failed(netif); break; } case GNRC_LWMAC_RX_STATE_SUCCESSFUL: { - _rx_management_success(gnrc_netdev); + _rx_management_success(netif); break; } default: - gnrc_lwmac_rx_update(gnrc_netdev); + gnrc_lwmac_rx_update(netif); } /* If state has changed, reschedule main state machine */ - if (state_rx != gnrc_netdev->rx.state) { - lwmac_schedule_update(gnrc_netdev); + if (state_rx != netif->mac.rx.state) { + lwmac_schedule_update(netif); } } -static void _tx_management_stopped(gnrc_netdev_t *gnrc_netdev) +static void _tx_management_stopped(gnrc_netif2_t *netif) { gnrc_pktsnip_t *pkt; /* If there is packet remaining for retransmission, * retransmit it (i.e., the retransmission scheme of LWMAC). */ - if (gnrc_netdev->tx.packet != NULL) { + if (netif->mac.tx.packet != NULL) { LOG_WARNING("WARNING: [LWMAC] TX %d times retry\n", - gnrc_netdev->tx.tx_retry_count); - gnrc_netdev->tx.state = GNRC_LWMAC_TX_STATE_INIT; - gnrc_netdev->tx.wr_sent = 0; - gnrc_lwmac_tx_update(gnrc_netdev); + netif->mac.tx.tx_retry_count); + netif->mac.tx.state = GNRC_LWMAC_TX_STATE_INIT; + netif->mac.tx.wr_sent = 0; + gnrc_lwmac_tx_update(netif); } else { if ((pkt = gnrc_priority_pktqueue_pop( - &gnrc_netdev->tx.current_neighbor->queue))) { - gnrc_netdev->tx.tx_retry_count = 0; - gnrc_lwmac_tx_start(gnrc_netdev, pkt, gnrc_netdev->tx.current_neighbor); - gnrc_lwmac_tx_update(gnrc_netdev); + &netif->mac.tx.current_neighbor->queue))) { + netif->mac.tx.tx_retry_count = 0; + gnrc_lwmac_tx_start(netif, pkt, netif->mac.tx.current_neighbor); + gnrc_lwmac_tx_update(netif); } else { /* Shouldn't happen, but never observed this case */ - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_SLEEPING); + lwmac_set_state(netif, GNRC_LWMAC_SLEEPING); } } } -static void _tx_management_success(gnrc_netdev_t *gnrc_netdev) +static void _tx_management_success(gnrc_netif2_t *netif) { - if (gnrc_netdev->tx.current_neighbor == &(gnrc_netdev->tx.neighbors[0])) { + if (netif->mac.tx.current_neighbor == &(netif->mac.tx.neighbors[0])) { LOG_INFO("[LWMAC] Broadcast transmission done\n"); } - gnrc_lwmac_tx_stop(gnrc_netdev); + gnrc_lwmac_tx_stop(netif); /* In case have pending packets for the same receiver, continue to * send immediately, before the maximum transmit-limit */ - if ((gnrc_netdev_lwmac_get_tx_continue(gnrc_netdev)) && - (gnrc_netdev->tx.tx_burst_count < GNRC_LWMAC_MAX_TX_BURST_PKT_NUM)) { - lwmac_schedule_update(gnrc_netdev); + if ((gnrc_lwmac_get_tx_continue(netif)) && + (netif->mac.tx.tx_burst_count < GNRC_LWMAC_MAX_TX_BURST_PKT_NUM)) { + lwmac_schedule_update(netif); } else { - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_SLEEPING); + lwmac_set_state(netif, GNRC_LWMAC_SLEEPING); } } -static void _tx_management(gnrc_netdev_t *gnrc_netdev) +static void _tx_management(gnrc_netif2_t *netif) { - gnrc_lwmac_tx_state_t state_tx = gnrc_netdev->tx.state; + gnrc_lwmac_tx_state_t state_tx = netif->mac.tx.state; switch (state_tx) { case GNRC_LWMAC_TX_STATE_STOPPED: { - _tx_management_stopped(gnrc_netdev); + _tx_management_stopped(netif); break; } case GNRC_LWMAC_TX_STATE_FAILED: { /* If transmission failure, do not try burst transmissions and quit other * transmission attempts in this cycle for collision avoidance */ - gnrc_netdev_lwmac_set_tx_continue(gnrc_netdev, false); - gnrc_netdev_lwmac_set_quit_tx(gnrc_netdev, true); + gnrc_lwmac_set_tx_continue(netif, false); + gnrc_lwmac_set_quit_tx(netif, true); /* falls through */ /* TX packet will therefore be dropped. No automatic resending here, * we did our best. */ } case GNRC_LWMAC_TX_STATE_SUCCESSFUL: { - _tx_management_success(gnrc_netdev); + _tx_management_success(netif); break; } default: - gnrc_lwmac_tx_update(gnrc_netdev); + gnrc_lwmac_tx_update(netif); } /* If state has changed, reschedule main state machine */ - if (state_tx != gnrc_netdev->tx.state) { - lwmac_schedule_update(gnrc_netdev); + if (state_tx != netif->mac.tx.state) { + lwmac_schedule_update(netif); } } -static void _lwmac_update_listening(gnrc_netdev_t *gnrc_netdev) +static void _lwmac_update_listening(gnrc_netif2_t *netif) { /* In case has pending packet to send, clear rtt alarm thus to goto * transmission initialization (in SLEEPING management) right after the * listening period */ - if ((_next_tx_neighbor(gnrc_netdev) != NULL) || - (gnrc_netdev->tx.current_neighbor != NULL)) { - rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, gnrc_netdev); + if ((_next_tx_neighbor(netif) != NULL) || + (netif->mac.tx.current_neighbor != NULL)) { + rtt_handler(GNRC_LWMAC_EVENT_RTT_PAUSE, netif); } /* Set timeout for if there's no successful rx transaction that will * change state to SLEEPING. */ - if (!gnrc_lwmac_timeout_is_running(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD)) { - gnrc_lwmac_set_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD, GNRC_LWMAC_WAKEUP_DURATION_US); + if (!gnrc_lwmac_timeout_is_running(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD)) { + gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD, GNRC_LWMAC_WAKEUP_DURATION_US); } - else if (gnrc_lwmac_timeout_is_expired(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD)) { + else if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD)) { /* Dispatch first as there still may be broadcast packets. */ - gnrc_mac_dispatch(&gnrc_netdev->rx); + gnrc_mac_dispatch(&netif->mac.rx); - gnrc_netdev->lwmac.state = GNRC_LWMAC_SLEEPING; + netif->mac.lwmac.state = GNRC_LWMAC_SLEEPING; /* Enable duty cycling again */ - rtt_handler(GNRC_LWMAC_EVENT_RTT_RESUME, gnrc_netdev); + rtt_handler(GNRC_LWMAC_EVENT_RTT_RESUME, netif); - _gnrc_lwmac_set_netdev_state(gnrc_netdev, NETOPT_STATE_SLEEP); - gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); + _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_SLEEP); + gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); /* if there is a packet for transmission, schedule update to start * transmission initialization immediately. */ - gnrc_mac_tx_neighbor_t *neighbour = _next_tx_neighbor(gnrc_netdev); - if ((neighbour != NULL) || (gnrc_netdev->tx.current_neighbor != NULL)) { + gnrc_mac_tx_neighbor_t *neighbour = _next_tx_neighbor(netif); + if ((neighbour != NULL) || (netif->mac.tx.current_neighbor != NULL)) { /* This triggers packet sending procedure in sleeping immediately. */ - lwmac_schedule_update(gnrc_netdev); + lwmac_schedule_update(netif); return; } } - if (gnrc_priority_pktqueue_length(&gnrc_netdev->rx.queue) > 0) { + if (gnrc_priority_pktqueue_length(&netif->mac.rx.queue) > 0) { /* Do wake-up extension in each packet reception. */ - gnrc_lwmac_clear_timeout(gnrc_netdev, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_RECEIVING); + gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); + lwmac_set_state(netif, GNRC_LWMAC_RECEIVING); } } /* Main state machine. Call whenever something happens */ -static bool lwmac_update(gnrc_netdev_t *gnrc_netdev) +static bool lwmac_update(gnrc_netif2_t *netif) { - gnrc_netdev_lwmac_set_reschedule(gnrc_netdev, false); + gnrc_lwmac_set_reschedule(netif, false); - switch (gnrc_netdev->lwmac.state) { + switch (netif->mac.lwmac.state) { case GNRC_LWMAC_SLEEPING: { /* Quit scheduling transmission if 'quit-tx' flag is found set, thus * to avoid potential collisions with ongoing transmissions of other * neighbor nodes */ - if (gnrc_netdev_lwmac_get_quit_tx(gnrc_netdev)) { + if (gnrc_lwmac_get_quit_tx(netif)) { return false; } - _sleep_management(gnrc_netdev); + _sleep_management(netif); break; } case GNRC_LWMAC_LISTENING: { - _lwmac_update_listening(gnrc_netdev); + _lwmac_update_listening(netif); break; } case GNRC_LWMAC_RECEIVING: { - _rx_management(gnrc_netdev); + _rx_management(netif); break; } case GNRC_LWMAC_TRANSMITTING: { - _tx_management(gnrc_netdev); + _tx_management(netif); break; } default: - LOG_DEBUG("[LWMAC] No actions in state %u\n", gnrc_netdev->lwmac.state); + LOG_DEBUG("[LWMAC] No actions in state %u\n", netif->mac.lwmac.state); } - return gnrc_netdev_lwmac_get_reschedule(gnrc_netdev); + return gnrc_lwmac_get_reschedule(netif); } static void rtt_cb(void *arg) @@ -560,30 +693,30 @@ static void rtt_cb(void *arg) } } -void rtt_handler(uint32_t event, gnrc_netdev_t *gnrc_netdev) +void rtt_handler(uint32_t event, gnrc_netif2_t *netif) { uint32_t alarm; switch (event & 0xffff) { case GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING: { /* A new cycle starts, set sleep timing and initialize related MAC-info flags. */ - gnrc_netdev->lwmac.last_wakeup = rtt_get_alarm(); - alarm = _next_inphase_event(gnrc_netdev->lwmac.last_wakeup, + netif->mac.lwmac.last_wakeup = rtt_get_alarm(); + alarm = _next_inphase_event(netif->mac.lwmac.last_wakeup, RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_DURATION_US)); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_SLEEP_PENDING); - gnrc_netdev_lwmac_set_quit_tx(gnrc_netdev, false); - gnrc_netdev_lwmac_set_quit_rx(gnrc_netdev, false); - gnrc_netdev_lwmac_set_phase_backoff(gnrc_netdev, false); - gnrc_netdev->rx.rx_bad_exten_count = 0; - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_LISTENING); + gnrc_lwmac_set_quit_tx(netif, false); + gnrc_lwmac_set_quit_rx(netif, false); + gnrc_lwmac_set_phase_backoff(netif, false); + netif->mac.rx.rx_bad_exten_count = 0; + lwmac_set_state(netif, GNRC_LWMAC_LISTENING); break; } case GNRC_LWMAC_EVENT_RTT_SLEEP_PENDING: { /* Set next wake-up timing. */ - alarm = _next_inphase_event(gnrc_netdev->lwmac.last_wakeup, + alarm = _next_inphase_event(netif->mac.lwmac.last_wakeup, RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_SLEEPING); + lwmac_set_state(netif, GNRC_LWMAC_SLEEPING); break; } /* Set initial wake-up alarm that starts the cycle */ @@ -591,24 +724,24 @@ void rtt_handler(uint32_t event, gnrc_netdev_t *gnrc_netdev) LOG_DEBUG("[LWMAC] RTT: Initialize duty cycling\n"); alarm = rtt_get_counter() + RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_DURATION_US); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_SLEEP_PENDING); - gnrc_netdev_lwmac_set_dutycycle_active(gnrc_netdev, true); + gnrc_lwmac_set_dutycycle_active(netif, true); break; } case GNRC_LWMAC_EVENT_RTT_STOP: case GNRC_LWMAC_EVENT_RTT_PAUSE: { rtt_clear_alarm(); LOG_DEBUG("[LWMAC] RTT: Stop duty cycling, now in state %u\n", - gnrc_netdev->lwmac.state); - gnrc_netdev_lwmac_set_dutycycle_active(gnrc_netdev, false); + netif->mac.lwmac.state); + gnrc_lwmac_set_dutycycle_active(netif, false); break; } case GNRC_LWMAC_EVENT_RTT_RESUME: { LOG_DEBUG("[LWMAC] RTT: Resume duty cycling\n"); rtt_clear_alarm(); - alarm = _next_inphase_event(gnrc_netdev->lwmac.last_wakeup, + alarm = _next_inphase_event(netif->mac.lwmac.last_wakeup, RTT_US_TO_TICKS(GNRC_LWMAC_WAKEUP_INTERVAL_US)); rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); - gnrc_netdev_lwmac_set_dutycycle_active(gnrc_netdev, true); + gnrc_lwmac_set_dutycycle_active(netif, true); break; } default: @@ -622,17 +755,17 @@ void rtt_handler(uint32_t event, gnrc_netdev_t *gnrc_netdev) * @param[in] event type of event * @param[in] data optional parameter */ -static void _event_cb(netdev_t *dev, netdev_event_t event) +static void _lwmac_event_cb(netdev_t *dev, netdev_event_t event) { - gnrc_netdev_t *gnrc_netdev = (gnrc_netdev_t *) dev->context; + gnrc_netif2_t *netif = (gnrc_netif2_t *) dev->context; if (event == NETDEV_EVENT_ISR) { msg_t msg; msg.type = NETDEV_MSG_TYPE_EVENT; - msg.content.ptr = (void *) gnrc_netdev; + msg.content.ptr = (void *) netif; - if (msg_send(&msg, gnrc_netdev->pid) <= 0) { + if (msg_send(&msg, netif->pid) <= 0) { LOG_WARNING("WARNING: [LWMAC] gnrc_netdev: possibly lost interrupt.\n"); } } @@ -641,13 +774,12 @@ static void _event_cb(netdev_t *dev, netdev_event_t event) switch (event) { case NETDEV_EVENT_RX_STARTED: { LOG_DEBUG("[LWMAC] NETDEV_EVENT_RX_STARTED\n"); - gnrc_netdev_set_rx_started(gnrc_netdev, true); + gnrc_netif2_set_rx_started(netif, true); break; } case NETDEV_EVENT_RX_COMPLETE: { LOG_DEBUG("[LWMAC] NETDEV_EVENT_RX_COMPLETE\n"); - - gnrc_pktsnip_t *pkt = gnrc_netdev->recv(gnrc_netdev); + gnrc_pktsnip_t *pkt = netif->ops->recv(netif); /* Prevent packet corruption when a packet is sent before the previous * received packet has been downloaded. This happens e.g. when a timeout @@ -661,87 +793,121 @@ static void _event_cb(netdev_t *dev, netdev_event_t event) * TODO: transceivers might have 2 frame buffers, so make this optional */ if (pkt == NULL) { - gnrc_netdev_set_rx_started(gnrc_netdev, false); + gnrc_netif2_set_rx_started(netif, false); break; } - gnrc_netdev_set_rx_started(gnrc_netdev, false); + gnrc_netif2_set_rx_started(netif, false); - if (!gnrc_mac_queue_rx_packet(&gnrc_netdev->rx, 0, pkt)) { + if (!gnrc_mac_queue_rx_packet(&netif->mac.rx, 0, pkt)) { LOG_ERROR("ERROR: [LWMAC] Can't push RX packet @ %p, memory full?\n", pkt); gnrc_pktbuf_release(pkt); break; } - lwmac_schedule_update(gnrc_netdev); + lwmac_schedule_update(netif); break; } case NETDEV_EVENT_TX_STARTED: { - gnrc_netdev_set_tx_feedback(gnrc_netdev, TX_FEEDBACK_UNDEF); - gnrc_netdev_set_rx_started(gnrc_netdev, false); + gnrc_netif2_set_tx_feedback(netif, TX_FEEDBACK_UNDEF); + gnrc_netif2_set_rx_started(netif, false); break; } case NETDEV_EVENT_TX_COMPLETE: { - gnrc_netdev_set_tx_feedback(gnrc_netdev, TX_FEEDBACK_SUCCESS); - gnrc_netdev_set_rx_started(gnrc_netdev, false); - lwmac_schedule_update(gnrc_netdev); + gnrc_netif2_set_tx_feedback(netif, TX_FEEDBACK_SUCCESS); + gnrc_netif2_set_rx_started(netif, false); + lwmac_schedule_update(netif); break; } case NETDEV_EVENT_TX_NOACK: { - gnrc_netdev_set_tx_feedback(gnrc_netdev, TX_FEEDBACK_NOACK); - gnrc_netdev_set_rx_started(gnrc_netdev, false); - lwmac_schedule_update(gnrc_netdev); + gnrc_netif2_set_tx_feedback(netif, TX_FEEDBACK_NOACK); + gnrc_netif2_set_rx_started(netif, false); + lwmac_schedule_update(netif); break; } case NETDEV_EVENT_TX_MEDIUM_BUSY: { - gnrc_netdev_set_tx_feedback(gnrc_netdev, TX_FEEDBACK_BUSY); - gnrc_netdev_set_rx_started(gnrc_netdev, false); - lwmac_schedule_update(gnrc_netdev); + gnrc_netif2_set_tx_feedback(netif, TX_FEEDBACK_BUSY); + gnrc_netif2_set_rx_started(netif, false); + lwmac_schedule_update(netif); break; } default: LOG_WARNING("WARNING: [LWMAC] Unhandled netdev event: %u\n", event); } } + + /* Execute main state machine because something just happend*/ + while (gnrc_lwmac_get_reschedule(netif)) { + lwmac_update(netif); + } } -/** - * @brief Startup code and event loop of the LWMAC layer - * - * @param[in] args expects a pointer to the underlying netdev device - * - * @return never returns - */ -static void *_lwmac_thread(void *args) +static int _send(gnrc_netif2_t *netif, gnrc_pktsnip_t *pkt) { - gnrc_netdev_t *gnrc_netdev = (gnrc_netdev_t *)args; - netdev_t *dev = gnrc_netdev->dev; + if (!gnrc_mac_queue_tx_packet(&netif->mac.tx, 0, pkt)) { + gnrc_pktbuf_release(pkt); + LOG_WARNING("WARNING: [LWMAC] TX queue full, drop packet\n"); + return -ENOBUFS; + } - gnrc_netdev->pid = thread_getpid(); + lwmac_schedule_update(netif); - gnrc_netapi_opt_t *opt; - int res; - msg_t msg, reply, msg_queue[GNRC_LWMAC_IPC_MSG_QUEUE_SIZE]; + /* Execute main state machine because something just happend*/ + while (gnrc_lwmac_get_reschedule(netif)) { + lwmac_update(netif); + } - LOG_INFO("[LWMAC] Starting LWMAC\n"); + return 0; +} - /* RTT is used for scheduling wakeup */ - rtt_init(); +static void _lwmac_msg_handler(gnrc_netif2_t *netif, msg_t *msg) +{ + switch (msg->type) { + /* RTT raised an interrupt */ + case GNRC_LWMAC_EVENT_RTT_TYPE: { + if (gnrc_lwmac_get_dutycycle_active(netif)) { + rtt_handler(msg->content.value, netif); + lwmac_schedule_update(netif); + } + else { + LOG_DEBUG("[LWMAC] Ignoring late RTT event while duty-cycling is off\n"); + } + break; + } - /* Store pid globally, so that IRQ can use it to send msg */ - lwmac_pid = thread_getpid(); + /* An LWMAC timeout occurred */ + case GNRC_LWMAC_EVENT_TIMEOUT_TYPE: { + gnrc_lwmac_timeout_make_expire((gnrc_lwmac_timeout_t *) msg->content.ptr); + lwmac_schedule_update(netif); + break; + } - /* setup the MAC layers message queue */ - msg_init_queue(msg_queue, GNRC_LWMAC_IPC_MSG_QUEUE_SIZE); + default: { +#if ENABLE_DEBUG + DEBUG("[LWMAC]: unknown message type 0x%04x" + "(no message handler defined)\n", msg->type); +#endif + break; + } + } + + /* Execute main state machine because something just happend*/ + while (gnrc_lwmac_get_reschedule(netif)) { + lwmac_update(netif); + } +} + +static void _lwmac_init(gnrc_netif2_t *netif) +{ + netdev_t *dev; - /* register the event callback with the device driver */ - dev->event_callback = _event_cb; - dev->context = (void *) gnrc_netdev; + dev = netif->dev; + dev->event_callback = _lwmac_event_cb; - /* register the device to the network stack*/ - gnrc_netif_add(thread_getpid()); + /* RTT is used for scheduling wakeup */ + rtt_init(); - /* initialize low-level driver */ - dev->driver->init(dev); + /* Store pid globally, so that IRQ can use it to send msg */ + lwmac_pid = netif->pid; /* Enable RX- and TX-started interrupts */ netopt_enable_t enable = NETOPT_ENABLE; @@ -749,172 +915,29 @@ static void *_lwmac_thread(void *args) dev->driver->set(dev, NETOPT_TX_START_IRQ, &enable, sizeof(enable)); dev->driver->set(dev, NETOPT_TX_END_IRQ, &enable, sizeof(enable)); - uint16_t src_len = 8; + uint16_t src_len = IEEE802154_LONG_ADDRESS_LEN; dev->driver->set(dev, NETOPT_SRC_LEN, &src_len, sizeof(src_len)); /* Get own address from netdev */ - gnrc_netdev->l2_addr_len = dev->driver->get(dev, NETOPT_ADDRESS_LONG, - &gnrc_netdev->l2_addr, - IEEE802154_LONG_ADDRESS_LEN); - assert(gnrc_netdev->l2_addr_len > 0); + netif->l2addr_len = dev->driver->get(dev, NETOPT_ADDRESS_LONG, + &netif->l2addr, + IEEE802154_LONG_ADDRESS_LEN); /* Initialize broadcast sequence number. This at least differs from board * to board */ - gnrc_netdev->tx.bcast_seqnr = gnrc_netdev->l2_addr[0]; + netif->mac.tx.bcast_seqnr = netif->l2addr[0]; /* Reset all timeouts just to be sure */ - gnrc_lwmac_reset_timeouts(gnrc_netdev); + gnrc_lwmac_reset_timeouts(netif); /* Start duty cycling */ - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_START); + lwmac_set_state(netif, GNRC_LWMAC_START); #if (GNRC_LWMAC_ENABLE_DUTYCYLE_RECORD == 1) /* Start duty cycle recording */ - gnrc_netdev->lwmac.system_start_time_ticks = rtt_get_counter(); - gnrc_netdev->lwmac.last_radio_on_time_ticks = gnrc_netdev->lwmac.system_start_time_ticks; - gnrc_netdev->lwmac.awake_duration_sum_ticks = 0; - gnrc_netdev->lwmac.lwmac_info |= GNRC_LWMAC_RADIO_IS_ON; + netif->mac.lwmac.system_start_time_ticks = rtt_get_counter(); + netif->mac.lwmac.last_radio_on_time_ticks = netif->mac.lwmac.system_start_time_ticks; + netif->mac.lwmac.awake_duration_sum_ticks = 0; + netif->mac.lwmac.lwmac_info |= GNRC_LWMAC_RADIO_IS_ON; #endif - - /* start the event loop */ - while (1) { - msg_receive(&msg); - - /* Handle NETDEV, NETAPI, RTT and TIMEOUT messages */ - switch (msg.type) { - /* RTT raised an interrupt */ - case GNRC_LWMAC_EVENT_RTT_TYPE: { - if (gnrc_netdev_lwmac_get_dutycycle_active(gnrc_netdev)) { - rtt_handler(msg.content.value, gnrc_netdev); - lwmac_schedule_update(gnrc_netdev); - } - else { - LOG_DEBUG("[LWMAC] Ignoring late RTT event while dutycycling is off\n"); - } - break; - } - /* An LWMAC timeout occured */ - case GNRC_LWMAC_EVENT_TIMEOUT_TYPE: { - gnrc_lwmac_timeout_make_expire((gnrc_lwmac_timeout_t *) msg.content.ptr); - lwmac_schedule_update(gnrc_netdev); - break; - } - /* Transceiver raised an interrupt */ - case NETDEV_MSG_TYPE_EVENT: { - LOG_DEBUG("[LWMAC] GNRC_NETDEV_MSG_TYPE_EVENT received\n"); - /* Forward event back to driver */ - dev->driver->isr(dev); - break; - } - /* TX: Queue for sending */ - case GNRC_NETAPI_MSG_TYPE_SND: { - /* TODO: how to announce failure to upper layers? */ - LOG_DEBUG("[LWMAC] GNRC_NETAPI_MSG_TYPE_SND received\n"); - gnrc_pktsnip_t *pkt = (gnrc_pktsnip_t *) msg.content.ptr; - - if (!gnrc_mac_queue_tx_packet(&gnrc_netdev->tx, 0, pkt)) { - gnrc_pktbuf_release(pkt); - LOG_WARNING("WARNING: [LWMAC] TX queue full, drop packet\n"); - } - - lwmac_schedule_update(gnrc_netdev); - break; - } - /* NETAPI set/get. Can't this be refactored away from here? */ - case GNRC_NETAPI_MSG_TYPE_SET: { - LOG_DEBUG("[LWMAC] GNRC_NETAPI_MSG_TYPE_SET received\n"); - opt = (gnrc_netapi_opt_t *)msg.content.ptr; - - /* Depending on option forward to NETDEV or handle here */ - switch (opt->opt) { - /* Handle state change requests */ - case NETOPT_STATE: { - netopt_state_t *state = (netopt_state_t *) opt->data; - res = opt->data_len; - switch (*state) { - case NETOPT_STATE_OFF: { - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_STOP); - break; - } - case NETOPT_STATE_IDLE: { - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_START); - break; - } - case NETOPT_STATE_RESET: { - lwmac_set_state(gnrc_netdev, GNRC_LWMAC_RESET); - break; - } - default: - res = -EINVAL; - LOG_ERROR("ERROR: [LWMAC] NETAPI tries to set unsupported" - " state %u\n",*state); - } - lwmac_schedule_update(gnrc_netdev); - break; - } - /* Forward to netdev by default*/ - default: - /* set option for device driver */ - res = dev->driver->set(dev, opt->opt, opt->data, opt->data_len); - LOG_DEBUG("[LWMAC] Response of netdev->set: %i\n", res); - } - - /* send reply to calling thread */ - reply.type = GNRC_NETAPI_MSG_TYPE_ACK; - reply.content.value = (uint32_t)res; - msg_reply(&msg, &reply); - break; - } - case GNRC_NETAPI_MSG_TYPE_GET: { - /* TODO: filter out MAC layer options -> for now forward - everything to the device driver */ - LOG_DEBUG("[LWMAC] GNRC_NETAPI_MSG_TYPE_GET received\n"); - /* read incoming options */ - opt = (gnrc_netapi_opt_t *)msg.content.ptr; - /* get option from device driver */ - res = dev->driver->get(dev, opt->opt, opt->data, opt->data_len); - LOG_DEBUG("[LWMAC] Response of netdev->get: %i\n", res); - /* send reply to calling thread */ - reply.type = GNRC_NETAPI_MSG_TYPE_ACK; - reply.content.value = (uint32_t)res; - msg_reply(&msg, &reply); - break; - } - default: - LOG_ERROR("ERROR: [LWMAC] Unknown command %" PRIu16 "\n", msg.type); - break; - } - - /* Execute main state machine because something just happend*/ - while (gnrc_netdev_lwmac_get_reschedule(gnrc_netdev)) { - lwmac_update(gnrc_netdev); - } - } - - LOG_ERROR("ERROR: [LWMAC] terminated\n"); - - /* never reached */ - return NULL; -} - -kernel_pid_t gnrc_lwmac_init(char *stack, int stacksize, char priority, - const char *name, gnrc_netdev_t *dev) -{ - kernel_pid_t res; - - /* check if given netdev device is defined and the driver is set */ - if (dev == NULL || dev->dev == NULL) { - LOG_ERROR("ERROR: [LWMAC] No netdev supplied or driver not set\n"); - return -ENODEV; - } - - /* create new LWMAC thread */ - res = thread_create(stack, stacksize, priority, THREAD_CREATE_STACKTEST, - _lwmac_thread, (void *)dev, name); - if (res <= 0) { - LOG_ERROR("ERROR: [LWMAC] Couldn't create thread\n"); - return -EINVAL; - } - - return res; } diff --git a/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c b/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c index 5ec6686013..2ee4af3fd2 100644 --- a/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c +++ b/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c @@ -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; - - /* 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; - } + (((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; + } } } diff --git a/sys/net/gnrc/link_layer/lwmac/rx_state_machine.c b/sys/net/gnrc/link_layer/lwmac/rx_state_machine.c index 3f35ad7e68..7707453207 100644 --- a/sys/net/gnrc/link_layer/lwmac/rx_state_machine.c +++ b/sys/net/gnrc/link_layer/lwmac/rx_state_machine.c @@ -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)) {} } diff --git a/sys/net/gnrc/link_layer/lwmac/timeout.c b/sys/net/gnrc/link_layer/lwmac/timeout.c index 6291f2ee93..39fa8b7732 100644 --- a/sys/net/gnrc/link_layer/lwmac/timeout.c +++ b/sys/net/gnrc/link_layer/lwmac/timeout.c @@ -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]); } } } diff --git a/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c b/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c index 44df3bd520..c201b50968 100644 --- a/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c +++ b/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c @@ -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)) {} } diff --git a/sys/net/gnrc/netif2/gnrc_netif2_ieee802154.c b/sys/net/gnrc/netif2/gnrc_netif2_ieee802154.c index ffad686c39..6ffeb71658 100644 --- a/sys/net/gnrc/netif2/gnrc_netif2_ieee802154.c +++ b/sys/net/gnrc/netif2/gnrc_netif2_ieee802154.c @@ -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); -- GitLab