From 8970d751c43804c2e821bc874b36acf5c466f343 Mon Sep 17 00:00:00 2001 From: Teufelchen1 Date: Tue, 15 Jul 2025 11:38:37 +0200 Subject: [PATCH] net/lwmac: Remove deprecated lwmac module --- makefiles/deprecated_modules.inc.mk | 2 - makefiles/pseudomodules.inc.mk | 6 - sys/include/net/gnrc/lwmac/hdr.h | 113 -- sys/include/net/gnrc/lwmac/lwmac.h | 353 ------- sys/include/net/gnrc/lwmac/timeout.h | 100 -- sys/include/net/gnrc/lwmac/types.h | 218 ---- sys/include/net/gnrc/mac/types.h | 19 - sys/include/net/gnrc/netif/mac.h | 18 - sys/include/net/gnrc/nettype.h | 8 - sys/net/gnrc/Kconfig | 1 - sys/net/gnrc/Makefile | 3 - sys/net/gnrc/Makefile.dep | 8 - sys/net/gnrc/link_layer/lwmac/Kconfig | 150 --- sys/net/gnrc/link_layer/lwmac/Makefile | 3 - .../link_layer/lwmac/include/lwmac_internal.h | 392 ------- .../lwmac/include/rx_state_machine.h | 57 - .../lwmac/include/tx_state_machine.h | 62 -- sys/net/gnrc/link_layer/lwmac/lwmac.c | 970 ------------------ .../gnrc/link_layer/lwmac/lwmac_internal.c | 274 ----- .../gnrc/link_layer/lwmac/rx_state_machine.c | 439 -------- sys/net/gnrc/link_layer/lwmac/timeout.c | 147 --- .../gnrc/link_layer/lwmac/tx_state_machine.c | 814 --------------- sys/net/gnrc/link_layer/mac/internal.c | 12 - .../netif/init_devs/auto_init_at86rf215.c | 13 +- .../netif/init_devs/auto_init_at86rf2xx.c | 10 - .../gnrc/netif/init_devs/auto_init_kw41zrf.c | 10 - sys/ztimer/Makefile.include | 2 +- tests/net/gnrc_lwmac/Makefile | 38 - tests/net/gnrc_lwmac/README.md | 53 - tests/net/gnrc_lwmac/main.c | 47 - 30 files changed, 2 insertions(+), 4340 deletions(-) delete mode 100644 sys/include/net/gnrc/lwmac/hdr.h delete mode 100644 sys/include/net/gnrc/lwmac/lwmac.h delete mode 100644 sys/include/net/gnrc/lwmac/timeout.h delete mode 100644 sys/include/net/gnrc/lwmac/types.h delete mode 100644 sys/net/gnrc/link_layer/lwmac/Kconfig delete mode 100644 sys/net/gnrc/link_layer/lwmac/Makefile delete mode 100644 sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h delete mode 100644 sys/net/gnrc/link_layer/lwmac/include/rx_state_machine.h delete mode 100644 sys/net/gnrc/link_layer/lwmac/include/tx_state_machine.h delete mode 100644 sys/net/gnrc/link_layer/lwmac/lwmac.c delete mode 100644 sys/net/gnrc/link_layer/lwmac/lwmac_internal.c delete mode 100644 sys/net/gnrc/link_layer/lwmac/rx_state_machine.c delete mode 100644 sys/net/gnrc/link_layer/lwmac/timeout.c delete mode 100644 sys/net/gnrc/link_layer/lwmac/tx_state_machine.c delete mode 100644 tests/net/gnrc_lwmac/Makefile delete mode 100644 tests/net/gnrc_lwmac/README.md delete mode 100644 tests/net/gnrc_lwmac/main.c diff --git a/makefiles/deprecated_modules.inc.mk b/makefiles/deprecated_modules.inc.mk index dd05e7b9d2..62513a84b0 100644 --- a/makefiles/deprecated_modules.inc.mk +++ b/makefiles/deprecated_modules.inc.mk @@ -1,7 +1,5 @@ # Add deprecated modules here # Keep this list ALPHABETICALLY SORTED!!!!111elven -DEPRECATED_MODULES += gnrc_lwmac DEPRECATED_MODULES += gnrc_mac DEPRECATED_MODULES += gnrc_nettype_lorawan -DEPRECATED_MODULES += gnrc_nettype_lwmac DEPRECATED_MODULES += sema_deprecated diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index a6213e4399..9a5db8076b 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -172,12 +172,6 @@ PSEUDOMODULES += gnrc_nettype_ipv6_ext PSEUDOMODULES += gnrc_nettype_lorawan ## @} -## @defgroup net_gnrc_nettype_lwmac gnrc_nettype_lwmac -## Enables @ref GNRC_NETTYPE_LWMAC -## @{ -PSEUDOMODULES += gnrc_nettype_lwmac -## @} - ## @defgroup net_gnrc_nettype_ndn gnrc_nettype_ndn ## Enables @ref GNRC_NETTYPE_NDN ## @{ diff --git a/sys/include/net/gnrc/lwmac/hdr.h b/sys/include/net/gnrc/lwmac/hdr.h deleted file mode 100644 index 279407b108..0000000000 --- a/sys/include/net/gnrc/lwmac/hdr.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#pragma once - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Header definition LWMAC - * @internal - * @author Daniel Krebs - * @author Shuguo Zhuo - */ - -#include -#include - -#include "net/ieee802154.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief LWMAC WR (wake-up request packet, i.e., preamble packet) frame type - */ -#define GNRC_LWMAC_FRAMETYPE_WR (0x01U) - -/** - * @brief LWMAC WA (wake-up answer packet, i.e., preamble-ACK packet) frame type - */ -#define GNRC_LWMAC_FRAMETYPE_WA (0x02U) - -/** - * @brief LWMAC data frame type - */ -#define GNRC_LWMAC_FRAMETYPE_DATA (0x03U) - -/** - * @brief LWMAC data frame type with pending data transmission request - */ -#define GNRC_LWMAC_FRAMETYPE_DATA_PENDING (0x04U) - -/** - * @brief LWMAC broadcast frame type - */ -#define GNRC_LWMAC_FRAMETYPE_BROADCAST (0x05U) - -/** - * @brief LWMAC internal L2 address structure - */ -typedef struct { - uint8_t addr[IEEE802154_LONG_ADDRESS_LEN]; /**< address of node */ - uint8_t len; /**< address */ -} gnrc_lwmac_l2_addr_t; - -/** - * @brief Static initializer for l2_addr_t. - */ -#define GNRC_LWMAC_L2_ADDR_INITIAL { { 0 }, 0 } - -/** - * @brief LWMAC header - */ -typedef struct { - uint8_t type; /**< type of frame */ -} gnrc_lwmac_hdr_t; - -/** - * @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_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_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_frame_broadcast_t; - -/** - * @brief LWMAC unicast data frame - */ -typedef struct __attribute__((packed)) { - gnrc_lwmac_hdr_t header; /**< Data packet header type */ -} gnrc_lwmac_frame_data_t; - -#ifdef __cplusplus -} -#endif - -/** @} */ diff --git a/sys/include/net/gnrc/lwmac/lwmac.h b/sys/include/net/gnrc/lwmac/lwmac.h deleted file mode 100644 index ef8c6b2a9d..0000000000 --- a/sys/include/net/gnrc/lwmac/lwmac.h +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#pragma once - -/** - * @defgroup net_gnrc_lwmac LWMAC - * @ingroup net_gnrc - * @brief A Lightweight duty-cycling 802.15.4 MAC protocol - * @deprecated This module is deprecated and will be removed after the 2024.10 release. - * As an alternative MAC layer for IEEE 802.15.4, you can use @ref pkg_opendsme. - * - * - * ## LWMAC implementation - * - * ## Radio duty cycling - * LWMAC adopts the radio duty-cycle scheme to conserve power. Namely, in each - * cycle period (MAC superframe), a node device wakes up for a short period of - * time (called listen period or wake-up period) for receiving possible incoming - * packets from other devices. Outside the listen period, the node device turns - * off its radio to conserve power. - * - * ## Phase-lock scheme - * LWMAC adopts the phase-lock scheme to further reduce power consumption. Each - * node device in LWMAC will try to record/track its Tx-neighbor's wake-up phase. - * This is called phase-lock. After phase-locking, the sender node will (likely) - * spend less preamble packets (also called WR packet, i.e., wake-up-request, in - * LWMAC) for initiating a hand-shaking procedure for transmitting a data packet, - * compared to the first time it talks to the receiver. - * - * ## Burst transmission - * LWMAC adopts pending-bit technique to enhance its throughput. Namely, in case - * of having multi packets for the receiver, a sender uses the pending-bit flag - * embedded in the MAC header to instruct this situation, and the buffered packets - * will be transmitted in a continuous sequence, back to back, to the receiver in - * one shot. - * - * ## Auto wake-up extension - * LWMAC adopts auto wake-up extension scheme based on timeout (like T-MAC). In short, - * when a packet is successfully received at the receiver side, the receiver will - * reset the wake-up timeout to extend its wake-up period for receiving more potential - * incoming packets. This is to be compatible with the pending-bit technique to allow - * the receiver to absorb more packets when needed, thus boosts the throughput. - * - * ## Simple retransmission scheme - * LWMAC adopts a simple retransmission scheme to enhance link reliability. The data - * packet will only be dropped in case the retransmission counter gets larger than - * @ref CONFIG_GNRC_LWMAC_MAX_DATA_TX_RETRIES. - * - * ## Automatic phase backoff scheme - * LWMAC adopts an automatic phase backoff scheme to reduce WR (preamble) collision - * probability. In multi-hop scenarios, let's say, nodes A <---B <----C (which is - * common in multi-hop data collection networks), in which B has packets for A, and - * C has packets for B. In case A and B's wake-up phases are too close (overlapping). - * Then, especially in high traffic conditions, B and C may initiate transmissions - * at the same time (B sends to A, and C sends to B), a link of either will be - * definitely interfered, leading to collisions and link throughput reduction. To - * this end, by using the automatic phase backoff scheme, if a sender finds its - * receiver's phase is too close to its own phase, it will run a backoff scheme to - * randomly reselect a new wake-up phase for itself. - * - * @{ - * - * @file - * @brief Interface definition for the LWMAC protocol - * - * @author Daniel Krebs - * @author Shuguo Zhuo - */ - -#include "net/gnrc/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @defgroup net_gnrc_lwmac_conf GNRC LWMAC compile configurations - * @ingroup net_gnrc_conf - * @{ - */ -/** - * @brief Time between consecutive wake-ups. - * - * This macro governs power consumption, latency and throughput! - * In LWMAC, devices adopt duty-cycle scheme to conserve power. That is, - * time is divided into repeated cycles (or, superframes), and in each - * cycle, a node only wakes up for a period of time for receiving potential - * incoming packets for itself. This macro defines the wake-up interval, or, - * in other words, defines the cycle duration used in LWMAC. If the wake-up - * interval is short, nodes will wake up more frequently, which also increases - * the chances for receiving packets from neighbors (i.e., leads to higher - * throughput), but also results in higher power consumption. - * In LWMAC, by default, we regard the wake-up period as the beginning of a - * cycle. - */ -#ifndef CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US -#define CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US (200LU *US_PER_MS) -#endif - -/** - * @brief The Maximum WR (preamble packet @ref gnrc_lwmac_frame_wr_t) duration - * time. - * - * Since LWMAC adopts duty-cycle scheme, a node only wakes up for a short - * period in each cycle. Thus, to probe where is the wake-up period of the - * receiver, a sender sends WR (preamble) packets to notice the receiver for - * communication. To ensure that the receiver will catch at least one WR - * packet in one cycle, the sender repeatedly broadcasts a stream of WR packets - * with the broadcast duration (preamble duration) slightly longer period than - * @ref CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US. - */ -#ifndef GNRC_LWMAC_PREAMBLE_DURATION_US -#define GNRC_LWMAC_PREAMBLE_DURATION_US ((13LU * CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US) / 10) -#endif - -/** - * @brief Timeout to send the next WR in case no WA has been received during - * that time. - * - * In LWMAC, when a sender initiates a transmission to a receiver, it starts - * with sending a stream of repeated WR packets with - * @ref CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US interval between two consecutive - * WRs. After sending one WR (preamble) packet, the sender turns to the listen - * mode to receive the potential incoming WA (preamble-ACK) packet with a - * timeout of @ref CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US. If no WA is received - * during @ref CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US, the sender starts sending - * the next WR. It is referenced to the beginning of both WRs, but due to - * internal overhead, the exact spacing is slightly higher. The minimum - * possible value depends on the time it takes to completely send a WR with the - * given hardware (including processor) and data rate. - */ -#ifndef CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US -#define CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US (5U *US_PER_MS) -#endif - -/** - * @brief How long a node in LWMAC should keep awake and listen on the channel - * in one cycle. - * - * LWMAC adopts the duty-cycle scheme that a node only wakes up for a short - * period of @ref GNRC_LWMAC_WAKEUP_DURATION_US in each cycle. In the rest of - * the cycle, the node turns off the radio to conserve power. - * @ref GNRC_LWMAC_WAKEUP_DURATION_US is set to twice the duration of - * @ref CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US, to guarantee that the wake-up - * period is long enough that receiver will not miss the WR (preamble) packet. - * Receiver needs to support @ref NETDEV_EVENT_RX_STARTED event in order to use - * time-between-WR as a sensible default here. Otherwise the duration of WRs as - * well as longest possible data broadcasts need to be taken into account. - */ -#ifndef GNRC_LWMAC_WAKEUP_DURATION_US -#define GNRC_LWMAC_WAKEUP_DURATION_US (CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US * 2) -#endif - -/** - * @brief How long broadcast packets @ref gnrc_lwmac_frame_broadcast_t will be - * sent to make sure every participant has received at least one copy. - * - * Since LWMAC adopts duty-cycle scheme, a node only wakes up for a short - * period in each cycle. Thus, when a node wants to broadcast a packet, it - * repeatedly broadcasts the packet for one - * @ref GNRC_LWMAC_BROADCAST_DURATION_US duration which is slightly longer - * than @ref CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US. This is to ensure that all - * neighbors will not miss the broadcast procedure of the sender and catch at - * least one copy of the broadcast packet. - */ -#ifndef GNRC_LWMAC_BROADCAST_DURATION_US -#define GNRC_LWMAC_BROADCAST_DURATION_US ((CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US * 11) / 10) -#endif - -/** - * @brief Time to idle between two successive broadcast packets, referenced to - * the start of the packet. - * - * The same limitation as for @ref CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US apply - * here. In LWMAC, when a sender initiates a broadcast, it starts with sending - * a stream ofrepeated broadcast packets with - * @ref GNRC_LWMAC_TIME_BETWEEN_BROADCAST_US interval between two consecutive - * broadcast packets. After sending one broadcast packet, the sender turns to - * the listen mode with a timeout of - * @ref GNRC_LWMAC_TIME_BETWEEN_BROADCAST_US. When this timeout expires, the - * sender sends the next broadcast packet until reaching the maximum broadcast - * duration of @ref GNRC_LWMAC_BROADCAST_DURATION_US. - */ -#ifndef GNRC_LWMAC_TIME_BETWEEN_BROADCAST_US -#define GNRC_LWMAC_TIME_BETWEEN_BROADCAST_US (CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US) -#endif - -/** - * @brief WR preparation overhead before it can be sent (higher with debugging - * output). - * - * In LWMAC, when a sender wants to send a data packet to the receiver, it - * starts sending the WR stream a little bit earlier (advance) to the beginning - * edge of destination's wake-up phase over time. The idea is not to miss the - * wake-up period of the receiver, otherwise will lead to a long WR procedure. - */ -#ifndef CONFIG_GNRC_LWMAC_WR_PREPARATION_US -#define CONFIG_GNRC_LWMAC_WR_PREPARATION_US ((3U *US_PER_MS)) -#endif - -/** - * @brief How long to wait after a WA for data to come in. - * - * When a node in LWMAC gets a WR during its wake-up period, it immediately - * replies a WA packet to the sender for acknowledging the sender's transmission - * request. After sending the WA, the receiver waits for the data packet from - * the sender, with a timeout of @ref CONFIG_GNRC_LWMAC_DATA_DELAY_US duration. - * In case no data will be received in this period, the receiver regards - * reception failed and go back to normal listen mode. However, in case the - * receiver receives other unintended packets, like WR/WA packets from other - * neighbor communication pairs, the receiver resets this timeout and continues - * to wait for the data packet, with the consideration that the sender's data - * transmission might be delayed due to other ongoing transmissions (the data - * packet is transmitted with CSMA/CA). This data timeout is long enough to - * catch the beginning of the packet if the transceiver supports - * @ref NETDEV_EVENT_RX_STARTED event (this can be important for big packets). - */ -#ifndef CONFIG_GNRC_LWMAC_DATA_DELAY_US -#define CONFIG_GNRC_LWMAC_DATA_DELAY_US (10U *US_PER_MS) -#endif - -/** - * @brief CSMA retries for DATA packet after WR->WA was successful. - * - * After receiving the WA packet @ref gnrc_lwmac_frame_wa_t from the receiver, - * the sender starts sending the data packet using CSMA/CA. This macro defines - * how many CSMA retries a sender will be allowed to execute for sending its - * data, before the data is successfully sent (gets data ACK from the receiver). - */ -#ifndef CONFIG_GNRC_LWMAC_DATA_CSMA_RETRIES -#define CONFIG_GNRC_LWMAC_DATA_CSMA_RETRIES (3U) -#endif - -/** - * @brief Maximum TX transmission retries for DATA packet in case of no - * response from the receiver. - * - * When a data packet is scheduled for transmission, i.e., pushed into TX for - * sending, LWMAC defines a maximum of - * @ref CONFIG_GNRC_LWMAC_MAX_DATA_TX_RETRIES retries for transmission of the - * packet. That is, in case of transmission failure in TX due to no WA from the - * receiver, the sender will not drop the packet, but keeps it and retries to - * send the data packet in the following cycles, until the sender reaches the - * maximum retries limit defined here. Then, the packet will be dropped. - */ -#ifndef CONFIG_GNRC_LWMAC_MAX_DATA_TX_RETRIES -#define CONFIG_GNRC_LWMAC_MAX_DATA_TX_RETRIES (3U) -#endif - -/** - * @brief MAX burst transmission packet number in one shot. - * - * LWMAC supports burst transmission based on the pending-bit technique, and - * this macro here defines the largest number of packets allowed to be sent in - * one consecutive sequence. In case a sender has multi packets for one - * receiver,the burst transmission procedure is as follows: - * - * 1. The sender first uses WR stream to locate the receiver's wake-up period - * (if the sender has already phase-locked the receiver's phase, normally - * the sender only cost one WR to get the first WA from the receiver) and - * then sends its first data. - * 2. After the transmission of the first data, the sender immediately sends a - * WR to the receiver for starting the second round of transmission of the - * second data. The receiver should also immediately reply WA for continue - * receiving data packets. In case the sender doesn't receive WA during - * @ref CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US, it regards the consecutive - * (burst) transmission failed and quits TX procedure (the data will be - * queued back to the transmission queue for normal transmission attempt in - * following cycles). - * 3. In case the second transmission succeeds, the sender repeats step (2) to - * send all the following pending packets. - * - * In short, in burst transmission mode, the sender doesn't tolerate no-WA - * event. All the pending data packets should be sent with only one WR cost for - * leading the transmission. - */ -#ifndef GNRC_LWMAC_MAX_TX_BURST_PKT_NUM -#define GNRC_LWMAC_MAX_TX_BURST_PKT_NUM \ - (CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US / GNRC_LWMAC_WAKEUP_DURATION_US) -#endif - -/** - * @brief MAX bad Listen period extensions a node can tolerate. - * - * In LWMAC, to allow burst transmissions, when in the wake-up period and by - * default, a node will extend its wake-up period to another - * @ref GNRC_LWMAC_WAKEUP_DURATION_US after each packet reception (except for - * broadcast packet). However, in some cases, a receiver may overhear other - * unintended packets, e.g., WR or WA packets for other nodes, these are called - * bad extensions for the receiver. If a receiver reaches the maximum bad listen - * extension limit defined here, it goes to sleep mode with the consideration - * that the channel is currently unavailable/busy. - */ -#ifndef CONFIG_GNRC_LWMAC_MAX_RX_EXTENSION_NUM -#define CONFIG_GNRC_LWMAC_MAX_RX_EXTENSION_NUM (3U) -#endif - -/** - * @brief CSMA retries for broadcast packet. - * - * Currently, each broadcast packet is sent with CSMA/CA for collision - * avoidance. - * - * @note Too many CSMA retries may lead to running out of destinations - * wake-up period. - */ -#ifndef CONFIG_GNRC_LWMAC_BROADCAST_CSMA_RETRIES -#define CONFIG_GNRC_LWMAC_BROADCAST_CSMA_RETRIES (3U) -#endif -/** @} */ - -/** -* @brief Maximum preamble attempts before re-initialize radio in LWMAC. -* -* After a long period of run time, a radio may be in wrong condition which needs to be -* re-calibrated. This is indicated by having a series of continuous preamble failure (no WA) -* in LWMAC. In case we have @ref CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD number of preamble -* failure, then we re-initialize the radio, trying to re-calibrate the radio for bringing it -* back to normal condition. -*/ -#ifndef CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD -#define CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD (10U) -#endif - -/** - * @brief Creates an IEEE 802.15.4 LWMAC network interface - * - * @param[out] netif The interface. May not be `NULL`. - * @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 - * - * @see @ref gnrc_netif_create() - * - * @return 0 on success - * @return negative number on error - */ -int gnrc_netif_lwmac_create(gnrc_netif_t *netif, char *stack, int stacksize, - char priority, const 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 deleted file mode 100644 index a83265dc79..0000000000 --- a/sys/include/net/gnrc/lwmac/timeout.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#pragma once - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Timeout handling of LWMAC - * - * - * @author Daniel Krebs - * @author Shuguo Zhuo - */ - -#include -#include - -#include "net/gnrc/netif.h" -#include "net/gnrc/lwmac/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Static initializer for @ref gnrc_lwmac_timeout_t. - */ -#define GNRC_LWMAC_TIMEOUT_INITIAL { {}, {}, false, TIMEOUT_DISABLED } - -/** - * @brief Set LWMAC timeout of type @p type of offset @p offset. - * - * @param[in,out] netif the network interface - * @param[in] type LWMAC timeout type - * @param[in] offset timeout offset - */ -void gnrc_lwmac_set_timeout(gnrc_netif_t *netif, - gnrc_lwmac_timeout_type_t type, - uint32_t offset); - -/** - * @brief Clear LWMAC timeout of type @p type. - * - * @param[in,out] netif the network interface - * @param[in] type LWMAC timeout type - */ -void gnrc_lwmac_clear_timeout(gnrc_netif_t *netif, gnrc_lwmac_timeout_type_t type); - -/** - * @brief Check whether LWMAC timeout of type @p type is running. - * - * @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_netif_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] 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_netif_t *netif, gnrc_lwmac_timeout_type_t type); - -/** - * @brief Reset all LWMAC timeouts. - * - * @param[in,out] netif the network interface - */ -void gnrc_lwmac_reset_timeouts(gnrc_netif_t *netif); - -/** - * @brief Make a specific LWMAC timeout expired. - * - * @param[in,out] timeout LWMAC timeout - */ -void gnrc_lwmac_timeout_make_expire(gnrc_lwmac_timeout_t *timeout); - -#ifdef __cplusplus -} -#endif - -/** @} */ diff --git a/sys/include/net/gnrc/lwmac/types.h b/sys/include/net/gnrc/lwmac/types.h deleted file mode 100644 index 5ba6967762..0000000000 --- a/sys/include/net/gnrc/lwmac/types.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#pragma once - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Definition of internal types used by LWMAC - * - * - * @author Daniel Krebs - * @author Shuguo Zhuo - */ - -#include "msg.h" -#include "xtimer.h" -#include "net/gnrc/lwmac/hdr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief LWMAC RTT event type. - */ -#define GNRC_LWMAC_EVENT_RTT_TYPE (0x4300) - -/** - * @brief LWMAC RTT start event type. - */ -#define GNRC_LWMAC_EVENT_RTT_START (0x4301) - -/** - * @brief LWMAC RTT stop event type. - */ -#define GNRC_LWMAC_EVENT_RTT_STOP (0x4302) - -/** - * @brief LWMAC RTT pause event type. - */ -#define GNRC_LWMAC_EVENT_RTT_PAUSE (0x4303) - -/** - * @brief LWMAC RTT resume event type. - */ -#define GNRC_LWMAC_EVENT_RTT_RESUME (0x4304) - -/** - * @brief LWMAC RTT wakeup pending event type. - */ -#define GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING (0x4305) - -/** - * @brief LWMAC RTT sleep pending event type. - */ -#define GNRC_LWMAC_EVENT_RTT_SLEEP_PENDING (0x4306) - -/** - * @brief LWMAC timeout event type. - */ -#define GNRC_LWMAC_EVENT_TIMEOUT_TYPE (0x4400) - -/** - * @brief LWMAC duty-cycle active flag. - * - * Keep track of duty cycling to avoid late RTT events after stopping. - */ -#define GNRC_LWMAC_DUTYCYCLE_ACTIVE (0x01) - -/** - * @brief LWMAC needs reschedule flag. - * - * Used internally for rescheduling state machine update, e.g. after state - * transition caused in update. - */ -#define GNRC_LWMAC_NEEDS_RESCHEDULE (0x02) - -/** - * @brief LWMAC check radio's on/off state flag. - */ -#define GNRC_LWMAC_RADIO_IS_ON (0x04) - -/** - * @ingroup net_gnrc_lwmac_conf - * @{ - */ -/** - * @brief The default largest number of parallel timeouts in LWMAC - */ -#ifndef CONFIG_GNRC_LWMAC_TIMEOUT_COUNT -#define CONFIG_GNRC_LWMAC_TIMEOUT_COUNT (3U) -#endif -/** @} */ - -/** - * @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_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_t; - -/** - * @brief Static initializer for gnrc_lwmac_tx_state_t. - */ -#define GNRC_LWMAC_TX_STATE_INITIAL GNRC_LWMAC_TX_STATE_STOPPED - -/** - * @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_t; - -/** - * @brief Static initializer for gnrc_lwmac_rx_state_t. - */ -#define GNRC_LWMAC_RX_STATE_INITIAL GNRC_LWMAC_RX_STATE_STOPPED - -/** - * @brief LWMAC uninitialized phase value - */ -#define GNRC_LWMAC_PHASE_UNINITIALIZED (0) - -/** - * @brief LWMAC max phase value - */ -#define GNRC_LWMAC_PHASE_MAX (-1) - -/** - * @brief LWMAC timeout types - */ -typedef enum { - GNRC_LWMAC_TIMEOUT_DISABLED, /**< Timeout is disabled */ - 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; - -/** - * @brief LWMAC timeout structure - */ -typedef struct { - xtimer_t timer; /**< xtimer entity */ - msg_t msg; /**< msg entity */ - bool expired; /**< If type != DISABLED, this indicates if timeout has expired */ - gnrc_lwmac_timeout_type_t type; /**< timeout type */ -} gnrc_lwmac_timeout_t; - -/** - * @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 information (flags) */ - gnrc_lwmac_timeout_t timeouts[CONFIG_GNRC_LWMAC_TIMEOUT_COUNT]; /**< Store timeouts used for protocol */ - -#if (GNRC_MAC_ENABLE_DUTYCYCLE_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 */ -#endif -} gnrc_lwmac_t; - -#ifdef __cplusplus -} -#endif - -/** @} */ diff --git a/sys/include/net/gnrc/mac/types.h b/sys/include/net/gnrc/mac/types.h index eefaf803f0..52b75fa227 100644 --- a/sys/include/net/gnrc/mac/types.h +++ b/sys/include/net/gnrc/mac/types.h @@ -27,9 +27,6 @@ #include "net/gnrc/priority_pktqueue.h" #include "net/ieee802154.h" #include "net/gnrc/mac/mac.h" -#ifdef MODULE_GNRC_LWMAC -#include "net/gnrc/lwmac/types.h" -#endif #ifdef __cplusplus extern "C" { @@ -72,12 +69,6 @@ typedef struct { #if (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0) || defined(DOXYGEN) gnrc_pktsnip_t *dispatch_buffer[GNRC_MAC_DISPATCH_BUFFER_SIZE]; /**< dispatch packet buffer */ #endif /* (GNRC_MAC_DISPATCH_BUFFER_SIZE != 0) || defined(DOXYGEN) */ - -#ifdef MODULE_GNRC_LWMAC - gnrc_lwmac_l2_addr_t l2_addr; /**< Records the sender's address */ - gnrc_lwmac_rx_state_t state; /**< LWMAC specific internal reception state */ - uint8_t rx_bad_exten_count; /**< Count how many unnecessary RX extensions have been executed */ -#endif } gnrc_mac_rx_t; /** @@ -169,16 +160,6 @@ typedef struct { gnrc_priority_pktqueue_node_t _queue_nodes[GNRC_MAC_TX_QUEUE_SIZE]; /**< Shared buffer for TX queue nodes */ gnrc_pktsnip_t *packet; /**< currently scheduled packet for sending */ #endif /* (GNRC_MAC_TX_QUEUE_SIZE != 0) || defined(DOXYGEN) */ - -#ifdef MODULE_GNRC_LWMAC - gnrc_lwmac_tx_state_t state; /**< LWMAC specific internal transmission state */ - uint32_t wr_sent; /**< Count how many WRs were sent until WA received */ - uint32_t timestamp; /**< Records the receiver's current phase */ - uint8_t bcast_seqnr; /**< Sequence number for broadcast data to filter at receiver */ - uint8_t tx_burst_count; /**< Count how many consecutive packets have been transmitted */ - uint8_t tx_retry_count; /**< Count how many Tx-retrials have been executed before packet drop */ - uint8_t preamble_fail_counts; /**< Preamble trial failure count. */ -#endif } gnrc_mac_tx_t; /** diff --git a/sys/include/net/gnrc/netif/mac.h b/sys/include/net/gnrc/netif/mac.h index b3f21815fc..4d5cfc0273 100644 --- a/sys/include/net/gnrc/netif/mac.h +++ b/sys/include/net/gnrc/netif/mac.h @@ -45,20 +45,6 @@ extern "C" { */ #define GNRC_NETIF_MAC_INFO_CSMA_ENABLED (0x0100U) -#if defined(MODULE_GNRC_LWMAC) -/** - * @brief Data type to hold MAC protocols - */ -typedef union { -#ifdef MODULE_GNRC_LWMAC - /** - * @brief LWMAC specific structure object for storing LWMAC internal states. - */ - gnrc_lwmac_t lwmac; -#endif -} gnrc_mac_prot_t; -#endif - /** * @brief @ref net_gnrc_mac component of @ref gnrc_netif_mac_t */ @@ -93,10 +79,6 @@ typedef struct { */ gnrc_mac_tx_t tx; #endif /* ((GNRC_MAC_TX_QUEUE_SIZE != 0) || (CONFIG_GNRC_MAC_NEIGHBOR_COUNT == 0)) || DOXYGEN */ - -#if defined(MODULE_GNRC_LWMAC) - gnrc_mac_prot_t prot; -#endif } gnrc_netif_mac_t; #ifdef __cplusplus diff --git a/sys/include/net/gnrc/nettype.h b/sys/include/net/gnrc/nettype.h index c687e81b5c..85ca4fccb1 100644 --- a/sys/include/net/gnrc/nettype.h +++ b/sys/include/net/gnrc/nettype.h @@ -65,14 +65,6 @@ typedef enum { * @{ * @name Link layer */ -#if IS_USED(MODULE_GNRC_NETTYPE_LWMAC) || defined(DOXYGEN) - /** - * @brief Protocol is lwMAC - * @deprecated @ref net_gnrc_lwmac was deprecated and will be removed after - * the 2024.10 release together with this protocol type. - */ - GNRC_NETTYPE_LWMAC, -#endif #if IS_USED(MODULE_GNRC_NETTYPE_CUSTOM) || defined(DOXYGEN) GNRC_NETTYPE_CUSTOM, /**< Custom ethertype */ #endif diff --git a/sys/net/gnrc/Kconfig b/sys/net/gnrc/Kconfig index f67bea7d60..aa1bd5aabf 100644 --- a/sys/net/gnrc/Kconfig +++ b/sys/net/gnrc/Kconfig @@ -9,7 +9,6 @@ menu "GNRC Network stack" rsource "application_layer/dhcpv6/Kconfig" rsource "link_layer/lorawan/Kconfig" -rsource "link_layer/lwmac/Kconfig" rsource "link_layer/mac/Kconfig" rsource "netif/Kconfig" rsource "network_layer/ipv6/Kconfig" diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile index 516b1c8496..db9c427d94 100644 --- a/sys/net/gnrc/Makefile +++ b/sys/net/gnrc/Makefile @@ -55,9 +55,6 @@ endif ifneq (,$(filter gnrc_pkt,$(USEMODULE))) DIRS += pkt endif -ifneq (,$(filter gnrc_lwmac,$(USEMODULE))) - DIRS += link_layer/lwmac -endif ifneq (,$(filter gnrc_pktbuf_malloc,$(USEMODULE))) DIRS += pktbuf_malloc endif diff --git a/sys/net/gnrc/Makefile.dep b/sys/net/gnrc/Makefile.dep index 03688513c2..8e4db1bae1 100644 --- a/sys/net/gnrc/Makefile.dep +++ b/sys/net/gnrc/Makefile.dep @@ -499,11 +499,3 @@ endif ifneq (,$(filter gnrc_netif_pktq,$(USEMODULE))) USEMODULE += xtimer endif - -ifneq (,$(filter gnrc_lwmac,$(USEMODULE))) - USEMODULE += gnrc_netif - USEMODULE += gnrc_nettype_lwmac - USEMODULE += gnrc_mac - USEMODULE += xtimer - FEATURES_REQUIRED += periph_rtt -endif diff --git a/sys/net/gnrc/link_layer/lwmac/Kconfig b/sys/net/gnrc/link_layer/lwmac/Kconfig deleted file mode 100644 index 9f2a2f79cd..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/Kconfig +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright (c) 2020 Freie Universitaet Berlin -# -# This file is subject to the terms and conditions of the GNU Lesser -# General Public License v2.1. See the file LICENSE in the top level -# directory for more details. -# - -menu "GNRC LWMAC" - depends on USEMODULE_GNRC_LWMAC - -config GNRC_LWMAC_WAKEUP_INTERVAL_US - int "Time between consecutive wake-ups in microseconds" - default 200000 - help - Configure 'CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US', time between - consecutive wake-ups in microseconds. This configuration governs power - consumption, latency and throughput! In LWMAC, devices adopt duty-cycle - scheme to conserve power. That is, time is divided into repeated cycles - (or, superframes), and in each cycle, a node only wakes up for a period - of time for receiving potential incoming packets for itself. This - configuration defines the wake-up interval, or, in other words, defines - the cycle duration used in LWMAC. If the wake-up interval is short, - nodes will wake up more frequently, which also increases the chances - for receiving packets from neighbors (i.e., leads to higher throughput, - but also results in higher power consumption. In LWMAC, by default, we - regard the wake-up period as the beginning of a cycle. - -config GNRC_LWMAC_TIME_BETWEEN_WR_US - int "Timeout to send the next WR in microseconds" - default 5000 - help - Configure 'CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US', timeout to send the - next WR in case no WA has been received during that time in - microseconds.In LWMAC, when a sender initiates a transmission to a - receiver, it starts with sending a stream of repeated WR packets with - 'CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US' interval between two - consecutive WRs. After sending one WR (preamble) packet, the sender - turns to the listen mode to receive the potential incoming WA - (preamble-ACK) packet with a timeout of - 'CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US'. If no WA is received during - 'CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US', the sender starts sending - the next WR. It is referenced to the beginning of both WRs, but due to - internal overhead, the exact spacing is slightly higher. The minimum - possible value depends on the time it takes to completely send a WR - with the given hardware (including processor) and data rate. - -config GNRC_LWMAC_WR_PREPARATION_US - int "WR preparation overhead time in microseconds" - default 3000 - help - Configure 'CONFIG_GNRC_LWMAC_WR_PREPARATION_US', WR preparation overhead - before it can be sent (higher with debugging output).In LWMAC, when a - sender wants to send a data packet to the receiver, it starts sending - the WR stream a little bit earlier (advance) to the beginning edge of - destinations wake-up phase over time. The idea is not to miss the - wake-up period of the receiver, otherwise will lead to a long WR - procedure. - -config GNRC_LWMAC_DATA_DELAY_US - int "Time to wait after a WA in microseconds" - default 10000 - help - Configure 'CONFIG_GNRC_LWMAC_DATA_DELAY_US', time to wait after a WA - for data to arrive in microseconds. When a node in LWMAC gets a WR - during its wake-up period, it immediately replies a WA packet to the - sender for acknowledging the senders transmission request. After - sending the WA, the receiver waits for the data packet from the sender, - with a timeout of 'CONFIG_GNRC_LWMAC_DATA_DELAY_US' duration. In case - no data will be received in this period, the receiver regards - reception failed and go back to normal listen mode. However, in case the - receiver receives other unintended packets, like WR/WA packets from - other neighbor communication pairs, the receiver resets this timeout - and continues to wait for the data packet, with the consideration that - the senders data transmission might be delayed due to other ongoing - transmissions (the data packet is transmitted with CSMA/CA). This data - timeout is long enough to catch the beginning of the packet if the - transceiver supports 'NETDEV_EVENT_RX_STARTED' event (this can be - important for big packets). - -config GNRC_LWMAC_DATA_CSMA_RETRIES - int "Number of CSMA retries for DATA packet after WR->WA success" - default 3 - help - Configure 'CONFIG_GNRC_LWMAC_DATA_CSMA_RETRIES', number of CSMA retries - for DATA packet after WR->WA was successful. After receiving the WA - packet 'gnrc_lwmac_frame_wa_t' from the receiver, the sender starts - sending the data packet using CSMA/CA. This configuration defines how - many CSMA retries a sender will be allowed to execute for sending its - data, before the data is successfully sent (gets data ACK from the - receiver). - -config GNRC_LWMAC_MAX_DATA_TX_RETRIES - int "MAX number of TX retries for DATA packet" - default 3 - help - Configure 'CONFIG_GNRC_LWMAC_MAX_DATA_TX_RETRIES', the maximum number - of TX transmission retries for DATA packet in case of no response from - the receiver. When a data packet is scheduled for transmission, i.e., - pushed into TX for sending, LWMAC defines a maximum of - 'CONFIG_GNRC_LWMAC_MAX_DATA_TX_RETRIES' retries for transmission of the - packet. That is, in case of transmission failure in TX due to no WA - from the receiver, the sender will not drop the packet, but keeps it - and retries to send the data packet in the following cycles, until the - sender reaches the maximum retries limit defined here. Then, the packet - will be dropped. - -config GNRC_LWMAC_MAX_RX_EXTENSION_NUM - int "MAX number of bad listen period extensions" - default 3 - help - Configure 'CONFIG_GNRC_LWMAC_MAX_RX_EXTENSION_NUM', the maximum - number of bad listen period extensions a node can tolerate. In LWMAC, - to allow burst transmissions, when in the wake-up period and by - default, a node will extend its wake-up period to another - 'GNRC_LWMAC_WAKEUP_DURATION_US' after each packet reception (except for - broadcast packet). However, in some cases, a receiver may overhear other - unintended packets, e.g., WR or WA packets for other nodes, these are - called bad extensions for the receiver. If a receiver reaches the - maximum bad listen extension limit defined here, it goes to sleep mode - with the consideration that the channel is currently unavailable/busy. - -config GNRC_LWMAC_BROADCAST_CSMA_RETRIES - int "Number of CSMA retries for broadcast packet" - default 3 - help - Configure 'CONFIG_GNRC_LWMAC_BROADCAST_CSMA_RETRIES',the number of CSMA - retries for broadcast packet. Currently, each broadcast packet is sent - with CSMA/CA for collision avoidance. **Too many CSMA retries may lead - to running out of destinations wake-up period**. - -config GNRC_LWMAC_TIMEOUT_COUNT - int "MAX number of number of parallel timeouts" - default 3 - help - Configure 'CONFIG_GNRC_LWMAC_TIMEOUT_COUNT', the default value for the - maximum number of parallel timeouts in LWMAC. - -config GNRC_LWMAC_RADIO_REINIT_THRESHOLD - int "Maximum preamble attempts before re-initialize radio" - default 10 - help - Configure 'CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD', the maximum preamble - attempts before re-initialize radio. After a long period of run time, a radio - may be in wrong condition which needs to be re-calibrated. This is indicated - by having a series of continuous preamble failure (no WA) in LWMAC. In case - we have @ref GNRC_LWMAC_RADIO_REINI_THRESHOLD number of preamble failure, - then we re-initialize the radio, trying to re-calibrate the radio for bringing - it back to normal condition. - -endmenu # GNRC LWMAC diff --git a/sys/net/gnrc/link_layer/lwmac/Makefile b/sys/net/gnrc/link_layer/lwmac/Makefile deleted file mode 100644 index 4c75407016..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -MODULE = gnrc_lwmac - -include $(RIOTBASE)/Makefile.base diff --git a/sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h b/sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h deleted file mode 100644 index b5b037b962..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/include/lwmac_internal.h +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#pragma once - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Interface definition for internal functions of LWMAC protocol - * - * @author Daniel Krebs - * @author Shuguo Zhuo - */ - -#include - -#include "periph/rtt.h" -#include "net/gnrc/netif.h" -#include "net/gnrc/mac/types.h" -#include "net/gnrc/lwmac/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Flag to track if the sender can continue to transmit packet to - * the receiver in its TX procedure. - * - * LWMAC supports burst transmission based on the pending-bit technique. - * Namely, if the sender has multi packets for the same receiver, it can - * successively transmit its packets back to back with this flag set up, - * with the awareness that the receiver will also keep awake for receptions. - */ -#define GNRC_LWMAC_TX_CONTINUE (0x0008U) - -/** - * @brief Flag to track if the sender should quit Tx in current cycle. - * - * This flag is mainly for collision avoidance. In case a node overhears - * ongoing broadcast packets stream or other ongoing transmissions of - * other communication pairs during its wake-up period, it sets up this - * flag, which quits all its potential transmission attempts in this current - * cycle (started by the wake-up period), thus not to collide with other - * (neighbor) nodes' transmissions. - */ -#define GNRC_LWMAC_QUIT_TX (0x0010U) - -/** - * @brief Flag to track if the device need to reselect a new wake-up phase. - * - * This flag is mainly for potential collision avoidance. In multi-hop scenario, - * it could be dangerous that a sender's wake-up phase is close to its receiver's, - * which may lead to collisions when the sender is sending to the receiver while - * the sender's son nodes are also sending to the sender. To avoid this, in case a - * sender finds its phase close to its receiver's, it sets up this flag and then - * randomly reselects a new wake-up phase. - */ -#define GNRC_LWMAC_PHASE_BACKOFF (0x0020U) - -/** - * @brief Flag to track if the device needs to quit the wake-up (listening) procedure. - * - * LWMAC adopts an auto wake-up extension scheme. That is, normally, after each data - * reception in the wake-up period, it extends the wake-up period to another basic - * duration, thus to receive more potential incoming packets, which is also correlated to - * the pending-bit transmission scheme to support burst transmissions to boost throughput. - * However, in some situations, like receiving broadcast (stream) packet, the receiver - * should immediately goto sleep (by setting up this flag) after one reception, thus not - * to receive duplicate broadcast packets. - */ -#define GNRC_LWMAC_QUIT_RX (0x0040U) - -/** - * @brief Type to pass information about parsing. - */ -typedef struct { - gnrc_lwmac_hdr_t *header; /**< LWMAC header of packet */ - gnrc_lwmac_l2_addr_t src_addr; /**< copied source address of packet */ - gnrc_lwmac_l2_addr_t dst_addr; /**< copied destination address of packet */ -} gnrc_lwmac_packet_info_t; - -/** - * @brief Next RTT event must be at least this far in the future. - * - * When setting an RTT alarm to short in the future it could be possible that - * the counter already passed the calculated alarm before it could be set. - */ -#define GNRC_LWMAC_RTT_EVENT_MARGIN_TICKS (RTT_MS_TO_TICKS(2)) - -/** - * @brief set the @ref GNRC_LWMAC_TX_CONTINUE flag of the device - * - * @param[in] netif ptr to the network interface - * @param[in] tx_continue value for LWMAC tx-continue flag - * - */ -static inline void gnrc_lwmac_set_tx_continue(gnrc_netif_t *netif, bool tx_continue) -{ - if (tx_continue) { - netif->mac.mac_info |= GNRC_LWMAC_TX_CONTINUE; - } - else { - netif->mac.mac_info &= ~GNRC_LWMAC_TX_CONTINUE; - } -} - -/** - * @brief get the @ref GNRC_LWMAC_TX_CONTINUE flag of the device - * - * @param[in] netif ptr to the network interface - * - * @return true if tx continue - * @return false if tx will not continue - */ -static inline bool gnrc_lwmac_get_tx_continue(gnrc_netif_t *netif) -{ - return (netif->mac.mac_info & GNRC_LWMAC_TX_CONTINUE); -} - -/** - * @brief set the @ref GNRC_LWMAC_QUIT_TX flag of the device - * - * @param[in] netif ptr to the network interface - * @param[in] quit_tx value for @ref GNRC_LWMAC_QUIT_TX flag - * - */ -static inline void gnrc_lwmac_set_quit_tx(gnrc_netif_t *netif, bool quit_tx) -{ - if (quit_tx) { - netif->mac.mac_info |= GNRC_LWMAC_QUIT_TX; - } - else { - netif->mac.mac_info &= ~GNRC_LWMAC_QUIT_TX; - } -} - -/** - * @brief get the @ref GNRC_LWMAC_QUIT_TX flag of the device - * - * @param[in] netif ptr to the network interface - * - * @return true if quit tx - * @return false if will not quit tx - */ -static inline bool gnrc_lwmac_get_quit_tx(gnrc_netif_t *netif) -{ - return (netif->mac.mac_info & GNRC_LWMAC_QUIT_TX); -} - -/** - * @brief set the @ref GNRC_LWMAC_PHASE_BACKOFF flag of the device - * - * @param[in] netif ptr to the network interface - * @param[in] backoff value for LWMAC @ref GNRC_LWMAC_PHASE_BACKOFF flag - * - */ -static inline void gnrc_lwmac_set_phase_backoff(gnrc_netif_t *netif, bool backoff) -{ - if (backoff) { - netif->mac.mac_info |= GNRC_LWMAC_PHASE_BACKOFF; - } - else { - netif->mac.mac_info &= ~GNRC_LWMAC_PHASE_BACKOFF; - } -} - -/** - * @brief get the @ref GNRC_LWMAC_PHASE_BACKOFF flag of the device - * - * @param[in] netif ptr to the network interface - * - * @return true if will run phase-backoff - * @return false if will not run phase-backoff - */ -static inline bool gnrc_lwmac_get_phase_backoff(gnrc_netif_t *netif) -{ - return (netif->mac.mac_info & GNRC_LWMAC_PHASE_BACKOFF); -} - -/** - * @brief set the @ref GNRC_LWMAC_QUIT_RX flag of the device - * - * @param[in] netif ptr to the network interface - * @param[in] quit_rx value for LWMAC @ref GNRC_LWMAC_QUIT_RX flag - * - */ -static inline void gnrc_lwmac_set_quit_rx(gnrc_netif_t *netif, bool quit_rx) -{ - if (quit_rx) { - netif->mac.mac_info |= GNRC_LWMAC_QUIT_RX; - } - else { - netif->mac.mac_info &= ~GNRC_LWMAC_QUIT_RX; - } -} - -/** - * @brief get the @ref GNRC_LWMAC_QUIT_RX flag of the device - * - * @param[in] netif ptr to the network interface - * - * @return true if will quit rx - * @return false if will not quit rx - */ -static inline bool gnrc_lwmac_get_quit_rx(gnrc_netif_t *netif) -{ - return (netif->mac.mac_info & GNRC_LWMAC_QUIT_RX); -} - -/** - * @brief set the @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag of LWMAC - * - * @param[in] netif ptr to the network interface - * @param[in] active value for LWMAC @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag - * - */ -static inline void gnrc_lwmac_set_dutycycle_active(gnrc_netif_t *netif, bool active) -{ - if (active) { - netif->mac.prot.lwmac.lwmac_info |= GNRC_LWMAC_DUTYCYCLE_ACTIVE; - } - else { - netif->mac.prot.lwmac.lwmac_info &= ~GNRC_LWMAC_DUTYCYCLE_ACTIVE; - } -} - -/** - * @brief get the @ref GNRC_LWMAC_DUTYCYCLE_ACTIVE flag of LWMAC - * - * @param[in] netif ptr to the network interface - * - * @return true if active - * @return false if not active - */ -static inline bool gnrc_lwmac_get_dutycycle_active(gnrc_netif_t *netif) -{ - return (netif->mac.prot.lwmac.lwmac_info & GNRC_LWMAC_DUTYCYCLE_ACTIVE); -} - -/** - * @brief set the @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag of LWMAC - * - * @param[in] netif ptr to the network interface - * @param[in] reschedule value for @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag - * - */ -static inline void gnrc_lwmac_set_reschedule(gnrc_netif_t *netif, bool reschedule) -{ - if (reschedule) { - netif->mac.prot.lwmac.lwmac_info |= GNRC_LWMAC_NEEDS_RESCHEDULE; - } - else { - netif->mac.prot.lwmac.lwmac_info &= ~GNRC_LWMAC_NEEDS_RESCHEDULE; - } -} - -/** - * @brief get the @ref GNRC_LWMAC_NEEDS_RESCHEDULE flag of LWMAC - * - * @param[in] netif ptr to the network interface - * - * @return true if needs rescheduling - * @return false if no need for rescheduling - */ -static inline bool gnrc_lwmac_get_reschedule(gnrc_netif_t *netif) -{ - return (netif->mac.prot.lwmac.lwmac_info & GNRC_LWMAC_NEEDS_RESCHEDULE); -} - -/** - * @brief send a @ref net_gnrc_pkt "packet" over the network interface in LWMAC - * - * @internal - * - * @pre `netif != NULL && pkt != NULL` - * - * @note The function re-formats the content of @p pkt to a format expected - * by the netdev_driver_t::send() method of gnrc_netif_t::dev and - * releases the packet before returning (so no additional release - * should be required after calling this method). - * - * @param[in] netif The network interface. - * @param[in] pkt A packet to send. - * - * @return The number of bytes actually sent on success - * @return -EBADMSG, if the @ref net_gnrc_netif_hdr in @p pkt is missing - * or is in an unexpected format. - * @return -ENOTSUP, if sending @p pkt in the given format isn't supported - * (e.g. empty payload with Ethernet). - * @return Any negative error code reported by gnrc_netif_t::dev. - */ -int _gnrc_lwmac_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt); - -/** - * @brief Parse an incoming packet and extract important information. - * - * Copies addresses into @p info, but header points inside @p pkt. - * - * @param[in] pkt packet that will be parsed - * @param[out] info structure that will hold parsed information - * - * @return 0 if correctly parsed - * @return <0 on error - */ -int _gnrc_lwmac_parse_packet(gnrc_pktsnip_t *pkt, gnrc_lwmac_packet_info_t *info); - -/** - * @brief Shortcut to get the state of netdev. - * - * @param[in] netif ptr to the network interface - * - * @return state of netdev - */ -netopt_state_t _gnrc_lwmac_get_netdev_state(gnrc_netif_t *netif); - -/** - * @brief Shortcut to set the state of netdev - * - * @param[in] netif ptr to the network interface - * @param[in] devstate new state for netdev - */ -void _gnrc_lwmac_set_netdev_state(gnrc_netif_t *netif, netopt_state_t devstate); - -/** - * @brief Convert RTT ticks to device phase - * - * @param[in] ticks RTT ticks - * - * @return device phase - */ -static inline uint32_t _gnrc_lwmac_ticks_to_phase(uint32_t ticks) -{ - assert(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US != 0); - - return (ticks % RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US)); -} - -/** - * @brief Get device's current phase - * - * @return device phase - */ -static inline uint32_t _gnrc_lwmac_phase_now(void) -{ - return _gnrc_lwmac_ticks_to_phase(rtt_get_counter()); -} - -/** - * @brief Calculate how many ticks remaining to the targeted phase in the future - * - * @param[in] phase device phase - * - * @return RTT ticks - */ -static inline uint32_t _gnrc_lwmac_ticks_until_phase(uint32_t phase) -{ - long int tmp = phase - _gnrc_lwmac_phase_now(); - - if (tmp < 0) { - /* Phase in next interval */ - tmp += RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US); - } - - return (uint32_t)tmp; -} - -/** - * @brief Store the received packet to the dispatch buffer and remove possible - * duplicate packets. - * - * @param[in,out] buffer RX dispatch packet buffer - * @param[in] pkt received packet - * - * @return 0 if correctly stored - * @return <0 on error - */ -int _gnrc_lwmac_dispatch_defer(gnrc_pktsnip_t * buffer[], gnrc_pktsnip_t * pkt); - -#ifdef __cplusplus -} -#endif - -/** @} */ 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 deleted file mode 100644 index d587c9e6cb..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/include/rx_state_machine.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#pragma once - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Implementation of RX state machine - * - * @author Daniel Krebs - * @author Shuguo Zhuo - * @} - */ - -#include "net/gnrc/pkt.h" -#include "net/gnrc/netif.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Start LWMAC RX procedure to receive packet - * - * @param[in,out] netif ptr to the network interface - * - */ -void gnrc_lwmac_rx_start(gnrc_netif_t *netif); - -/** - * @brief Stop LWMAC RX procedure - * - * @param[in,out] netif ptr to the network interface - * - */ -void gnrc_lwmac_rx_stop(gnrc_netif_t *netif); - -/** - * @brief Update LWMAC RX procedure for packet reception - * - * @param[in,out] netif ptr to the network interface - * - */ -void gnrc_lwmac_rx_update(gnrc_netif_t *netif); - -#ifdef __cplusplus -} -#endif 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 deleted file mode 100644 index 1567e435be..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/include/tx_state_machine.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#pragma once - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Implementation of TX state machine - * - * @author Daniel Krebs - * @author Shuguo Zhuo - * @} - */ - -#include "net/gnrc/pkt.h" -#include "net/gnrc/netif.h" -#include "net/gnrc/mac/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Start LWMAC TX procedure to transmit packet @p pkt to @p neighbor - * - * @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_netif_t *netif, - gnrc_pktsnip_t *pkt, - gnrc_mac_tx_neighbor_t *neighbor); - -/** - * @brief Stop LWMAC TX procedure - * - * @param[in,out] netif ptr to the network interface - * - */ -void gnrc_lwmac_tx_stop(gnrc_netif_t *netif); - -/** - * @brief Update LWMAC TX procedure for transmission - * - * @param[in,out] netif ptr to the network interface - * - */ -void gnrc_lwmac_tx_update(gnrc_netif_t *netif); - -#ifdef __cplusplus -} -#endif diff --git a/sys/net/gnrc/link_layer/lwmac/lwmac.c b/sys/net/gnrc/link_layer/lwmac/lwmac.c deleted file mode 100644 index b53910607e..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/lwmac.c +++ /dev/null @@ -1,970 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Implementation of the LWMAC protocol - * - * @author Daniel Krebs - * @author Shuguo Zhuo - * @} - */ - -#include -#include -#include -#include -#include - -#include "event.h" -#include "od.h" -#include "timex.h" -#include "random.h" -#include "periph/rtt.h" -#include "net/gnrc/netif.h" -#include "net/gnrc/netif/hdr.h" -#include "net/gnrc/netif/internal.h" -#include "net/gnrc/netif/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" -#include "net/gnrc/lwmac/timeout.h" -#include "include/tx_state_machine.h" -#include "include/rx_state_machine.h" -#include "include/lwmac_internal.h" - -#ifndef LOG_LEVEL -/** - * @brief Default log level define - */ -#define LOG_LEVEL LOG_WARNING -#endif - -#include "log.h" - -#define ENABLE_DEBUG 0 -#include "debug.h" - -/** - * @brief LWMAC thread's PID - */ -kernel_pid_t lwmac_pid; - -static void rtt_cb(void *arg); -static void lwmac_set_state(gnrc_netif_t *netif, gnrc_lwmac_state_t newstate); -static void lwmac_schedule_update(gnrc_netif_t *netif); -static void rtt_handler(uint32_t event, gnrc_netif_t *netif); -static int _lwmac_init(gnrc_netif_t *netif); -static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt); -static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif); -static void _lwmac_msg_handler(gnrc_netif_t *netif, msg_t *msg); - -static const gnrc_netif_ops_t lwmac_ops = { - .init = _lwmac_init, - .send = _send, - .recv = _recv, - .get = gnrc_netif_get_from_netdev, - .set = gnrc_netif_set_from_netdev, - .msg_handler = _lwmac_msg_handler, -}; - -int gnrc_netif_lwmac_create(gnrc_netif_t *netif, char *stack, int stacksize, - char priority, const char *name, netdev_t *dev) -{ - return gnrc_netif_create(netif, stack, stacksize, priority, name, dev, - &lwmac_ops); -} - -static void lwmac_reinit_radio(gnrc_netif_t *netif) -{ - /* Initialize low-level driver. */ - netif->dev->driver->init(netif->dev); - - /* Set MAC address length. */ - uint16_t src_len = netif->l2addr_len; - netif->dev->driver->set(netif->dev, NETOPT_SRC_LEN, &src_len, sizeof(src_len)); - - /* Set the MAC address of the device. */ - if (netif->l2addr_len == IEEE802154_LONG_ADDRESS_LEN) { - netif->dev->driver->set(netif->dev, - NETOPT_ADDRESS_LONG, - netif->l2addr, - sizeof(netif->l2addr)); - } - else { - netif->dev->driver->set(netif->dev, - NETOPT_ADDR_LEN, - netif->l2addr, - sizeof(netif->l2addr)); - } - - /* Check if RX-start and TX-started and TX-END interrupts are supported */ - if (IS_ACTIVE(DEVELHELP)) { - netopt_enable_t enable; - netif->dev->driver->get(netif->dev, NETOPT_RX_START_IRQ, &enable, sizeof(enable)); - assert(enable == NETOPT_ENABLE); - netif->dev->driver->get(netif->dev, NETOPT_TX_END_IRQ, &enable, sizeof(enable)); - assert(enable == NETOPT_ENABLE); - } -} - -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_netif_t *netif) -{ - netdev_t *dev = netif->dev; - netdev_ieee802154_rx_info_t rx_info; - netdev_ieee802154_t *state = container_of(dev, netdev_ieee802154_t, netdev); - 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; - 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; - gnrc_netif_hdr_set_netif(hdr, netif); - pkt->type = state->proto; - if (IS_ACTIVE(ENABLE_DEBUG)) { - char src_str[GNRC_NETIF_HDR_L2ADDR_PRINT_LEN]; - - DEBUG("_recv_ieee802154: received packet from %s of length %u\n", - gnrc_netif_addr_to_str(gnrc_netif_hdr_get_src_addr(hdr), - hdr->src_l2addr_len, - src_str), - nread); - - if (IS_USED(MODULE_OD)) { - od_hex_dump(pkt->data, nread, OD_WIDTH_DEFAULT); - } - } - gnrc_pktbuf_remove_snip(pkt, ieee802154_hdr); - pkt = gnrc_pkt_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_netif_t *netif) -{ - gnrc_mac_tx_neighbor_t *next = NULL; - uint32_t phase_nearest = GNRC_LWMAC_PHASE_MAX; - - for (unsigned i = 0; i < CONFIG_GNRC_MAC_NEIGHBOR_COUNT; i++) { - 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(netif->mac.tx.neighbors[i].phase); - - if (phase_check <= phase_nearest) { - next = &(netif->mac.tx.neighbors[i]); - phase_nearest = phase_check; - DEBUG("[LWMAC-int] Advancing queue #%u\n", i); - } - } - } - - return next; -} - -static uint32_t _next_inphase_event(uint32_t last, uint32_t interval) -{ - /* Counter did overflow since last wakeup */ - if (rtt_get_counter() < last) { - /* TODO: Not sure if this was tested :) */ - uint32_t tmp = -last; - tmp /= interval; - tmp++; - last += tmp * interval; - } - - /* Add margin to next wakeup so that it will be at least 2ms in the future */ - while (last < (rtt_get_counter() + GNRC_LWMAC_RTT_EVENT_MARGIN_TICKS)) { - last += interval; - } - - return last; -} - -inline void lwmac_schedule_update(gnrc_netif_t *netif) -{ - gnrc_lwmac_set_reschedule(netif, true); -} - -void lwmac_set_state(gnrc_netif_t *netif, gnrc_lwmac_state_t newstate) -{ - gnrc_lwmac_state_t oldstate = netif->mac.prot.lwmac.state; - - if (newstate == oldstate) { - return; - } - - if (newstate >= GNRC_LWMAC_STATE_COUNT) { - LOG_ERROR("ERROR: [LWMAC] Trying to set invalid state %u\n", newstate); - return; - } - - /* Already change state, but might be reverted to oldstate when needed */ - netif->mac.prot.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, netif); - break; - } - case GNRC_LWMAC_SLEEPING: { - gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); - break; - } - default: - break; - } - - /* Actions when entering new state */ - switch (newstate) { - /*********************** Operation states *********************************/ - case GNRC_LWMAC_LISTENING: { - _gnrc_lwmac_set_netdev_state(netif, NETOPT_STATE_IDLE); - break; - } - case GNRC_LWMAC_SLEEPING: { - /* Put transceiver to 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(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD); - - if (gnrc_lwmac_get_phase_backoff(netif)) { - gnrc_lwmac_set_phase_backoff(netif, false); - uint32_t alarm; - - rtt_clear_alarm(); - alarm = random_uint32_range( - RTT_US_TO_TICKS((3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2)), - RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US - - (3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2))); - LOG_WARNING("WARNING: [LWMAC] phase backoffed: %lu us\n", - (unsigned long)RTT_TICKS_TO_US(alarm)); - netif->mac.prot.lwmac.last_wakeup = netif->mac.prot.lwmac.last_wakeup + alarm; - alarm = _next_inphase_event(netif->mac.prot.lwmac.last_wakeup, - RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US)); - rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); - } - - /* Return immediately, so no rescheduling */ - return; - } - /* Trying to send data */ - case GNRC_LWMAC_TRANSMITTING: { - 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, 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(netif, NETOPT_STATE_OFF); - break; - } - /*********************** Control states ***********************************/ - case GNRC_LWMAC_START: { - rtt_handler(GNRC_LWMAC_EVENT_RTT_START, netif); - lwmac_set_state(netif, GNRC_LWMAC_LISTENING); - netif->mac.tx.preamble_fail_counts = 0; - break; - } - case GNRC_LWMAC_STOP: { - 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(netif, GNRC_LWMAC_STOP); - lwmac_set_state(netif, GNRC_LWMAC_START); - break; - } - /**************************************************************************/ - default: { - LOG_DEBUG("[LWMAC] No actions for entering state %u\n", newstate); - return; - } - } - - lwmac_schedule_update(netif); -} - -static void _sleep_management(gnrc_netif_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(netif, GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP)) { - gnrc_mac_tx_neighbor_t *neighbour; - - /* Check if there is packet remaining for retransmission */ - 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(&(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(netif); - } - - if (neighbour != NULL) { - /* if phase is unknown, send immediately. */ - if (neighbour->phase > RTT_TICKS_TO_US(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US)) { - 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; - } - - /* Offset in microseconds when the earliest (phase) destination - * node wakes up that we have packets for. */ - uint32_t time_until_tx = RTT_TICKS_TO_US(_gnrc_lwmac_ticks_until_phase(neighbour->phase)); - - /* If there's not enough time to prepare a WR to catch the phase - * postpone to next interval */ - if (time_until_tx < CONFIG_GNRC_LWMAC_WR_PREPARATION_US) { - time_until_tx += CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US; - } - time_until_tx -= CONFIG_GNRC_LWMAC_WR_PREPARATION_US; - - /* add a random time before goto TX, for avoiding one node for - * always holding the medium (if the receiver's phase is recorded earlier in this - * particular node) */ - uint32_t random_backoff; - random_backoff = random_uint32_range(0, CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US); - time_until_tx = time_until_tx + random_backoff; - - gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP, time_until_tx); - - /* Register neighbour to be the next */ - 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, netif); - } - } - 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_lwmac_set_tx_continue(netif, false); - netif->mac.tx.tx_burst_count = 0; - lwmac_set_state(netif, GNRC_LWMAC_TRANSMITTING); - } -} - -static void _rx_management_attempt_sleep(gnrc_netif_t *netif) -{ - /* 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 < netif->mac.prot.lwmac.last_wakeup) { - phase = (RTT_US_TO_TICKS(GNRC_LWMAC_PHASE_MAX) - netif->mac.prot.lwmac.last_wakeup) + - phase; - } - else { - phase = phase - netif->mac.prot.lwmac.last_wakeup; - } - /* If the relative phase is beyond 4/5 cycle time, go to sleep. */ - if (phase > (4 * RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US) / 5)) { - gnrc_lwmac_set_quit_rx(netif, true); - } - - 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(netif, GNRC_LWMAC_LISTENING); - } -} - -static void _rx_management_failed(gnrc_netif_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(netif); - - if (netif->mac.rx.rx_bad_exten_count >= CONFIG_GNRC_LWMAC_MAX_RX_EXTENSION_NUM) { - gnrc_lwmac_set_quit_rx(netif, true); - } - - _rx_management_attempt_sleep(netif); -} - -static void _rx_management_success(gnrc_netif_t *netif) -{ - LOG_DEBUG("[LWMAC] Reception was successful\n"); - gnrc_lwmac_rx_stop(netif); - /* Dispatch received packets, timing is not critical anymore */ - gnrc_mac_dispatch(&netif->mac.rx); - - _rx_management_attempt_sleep(netif); -} - -static void _rx_management(gnrc_netif_t *netif) -{ - gnrc_lwmac_rx_state_t state_rx = netif->mac.rx.state; - - switch (state_rx) { - case GNRC_LWMAC_RX_STATE_STOPPED: { - gnrc_lwmac_rx_start(netif); - gnrc_lwmac_rx_update(netif); - break; - } - case GNRC_LWMAC_RX_STATE_FAILED: { - _rx_management_failed(netif); - break; - } - case GNRC_LWMAC_RX_STATE_SUCCESSFUL: { - _rx_management_success(netif); - break; - } - default: - gnrc_lwmac_rx_update(netif); - } - - /* If state has changed, reschedule main state machine */ - if (state_rx != netif->mac.rx.state) { - lwmac_schedule_update(netif); - } -} - -static void _tx_management_stopped(gnrc_netif_t *netif) -{ - /* If there is packet remaining for retransmission, - * retransmit it (i.e., the retransmission scheme of LWMAC). */ - if (netif->mac.tx.packet != NULL) { - LOG_WARNING("WARNING: [LWMAC] TX %d times retry\n", - 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 { - gnrc_pktsnip_t *pkt; - - if ((pkt = gnrc_priority_pktqueue_pop( - &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(netif, GNRC_LWMAC_SLEEPING); - } - } -} - -static void _tx_management_success(gnrc_netif_t *netif) -{ - if (netif->mac.tx.current_neighbor == &(netif->mac.tx.neighbors[0])) { - LOG_INFO("[LWMAC] Broadcast transmission done\n"); - } - - 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_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(netif, GNRC_LWMAC_SLEEPING); - } -} - -static void _tx_management(gnrc_netif_t *netif) -{ - gnrc_lwmac_tx_state_t state_tx = netif->mac.tx.state; - - switch (state_tx) { - case GNRC_LWMAC_TX_STATE_STOPPED: - _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_lwmac_set_tx_continue(netif, false); - gnrc_lwmac_set_quit_tx(netif, true); - /* TX packet will be dropped, no automatic resending here. */ - - /* Re-initialize the radio when needed. */ - if (netif->mac.tx.preamble_fail_counts >= CONFIG_GNRC_LWMAC_RADIO_REINIT_THRESHOLD) { - netif->mac.tx.preamble_fail_counts = 0; - LOG_INFO("[LWMAC] Re-initialize radio."); - lwmac_reinit_radio(netif); - } - /* Intentionally falls through */ - - case GNRC_LWMAC_TX_STATE_SUCCESSFUL: - _tx_management_success(netif); - break; - - default: - gnrc_lwmac_tx_update(netif); - break; - } - - /* If state has changed, reschedule main state machine */ - if (state_tx != netif->mac.tx.state) { - lwmac_schedule_update(netif); - } -} - -static void _lwmac_update_listening(gnrc_netif_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(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(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(netif, GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD)) { - /* Dispatch first as there still may be broadcast packets. */ - gnrc_mac_dispatch(&netif->mac.rx); - - netif->mac.prot.lwmac.state = GNRC_LWMAC_SLEEPING; - /* Enable duty cycling again */ - rtt_handler(GNRC_LWMAC_EVENT_RTT_RESUME, netif); - - _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(netif); - if ((neighbour != NULL) || (netif->mac.tx.current_neighbor != NULL)) { - /* This triggers packet sending procedure in sleeping immediately. */ - lwmac_schedule_update(netif); - return; - } - } - - if (gnrc_priority_pktqueue_length(&netif->mac.rx.queue) > 0) { - /* Do wake-up extension in each packet reception. */ - 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_netif_t *netif) -{ - gnrc_lwmac_set_reschedule(netif, false); - - switch (netif->mac.prot.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_lwmac_get_quit_tx(netif)) { - return false; - } - - _sleep_management(netif); - break; - } - case GNRC_LWMAC_LISTENING: { - _lwmac_update_listening(netif); - break; - } - case GNRC_LWMAC_RECEIVING: { - _rx_management(netif); - break; - } - case GNRC_LWMAC_TRANSMITTING: { - _tx_management(netif); - break; - } - default: - LOG_DEBUG("[LWMAC] No actions in state %u\n", netif->mac.prot.lwmac.state); - } - - return gnrc_lwmac_get_reschedule(netif); -} - -static void rtt_cb(void *arg) -{ - msg_t msg; - - msg.content.value = (uint16_t)((uintptr_t) arg); - msg.type = GNRC_LWMAC_EVENT_RTT_TYPE; - msg_send(&msg, lwmac_pid); - - if (sched_context_switch_request) { - thread_yield(); - } -} - -void rtt_handler(uint32_t event, gnrc_netif_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. */ - netif->mac.prot.lwmac.last_wakeup = rtt_get_alarm(); - alarm = _next_inphase_event(netif->mac.prot.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_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(netif->mac.prot.lwmac.last_wakeup, - RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US)); - rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); - lwmac_set_state(netif, GNRC_LWMAC_SLEEPING); - break; - } - /* Set initial wake-up alarm that starts the cycle */ - case GNRC_LWMAC_EVENT_RTT_START: { - 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_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", - netif->mac.prot.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(netif->mac.prot.lwmac.last_wakeup, - RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US)); - rtt_set_alarm(alarm, rtt_cb, (void *) GNRC_LWMAC_EVENT_RTT_WAKEUP_PENDING); - gnrc_lwmac_set_dutycycle_active(netif, true); - break; - } - default: - break; - } -} - -/** - * @brief Function called by the device driver on device events - * - * @param dev netdev causing the event - * @param[in] event type of event - */ -static void _lwmac_event_cb(netdev_t *dev, netdev_event_t event) -{ - gnrc_netif_t *netif = (gnrc_netif_t *) dev->context; - - if (event == NETDEV_EVENT_ISR) { - event_post(&netif->evq[GNRC_NETIF_EVQ_INDEX_PRIO_LOW], &netif->event_isr); - } - else { - DEBUG("gnrc_netdev: event triggered -> %i\n", event); - switch (event) { - case NETDEV_EVENT_RX_STARTED: { - LOG_DEBUG("[LWMAC] NETDEV_EVENT_RX_STARTED\n"); - gnrc_netif_set_rx_started(netif, true); - break; - } - case NETDEV_EVENT_RX_COMPLETE: { - LOG_DEBUG("[LWMAC] NETDEV_EVENT_RX_COMPLETE\n"); - 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 - * expires that causes the tx state machine to send a packet. When a - * packet arrives after the timeout, the notification is queued but the - * tx state machine continues to send and then destroys the received - * packet in the frame buffer. After completion, the queued notification - * will be handled a corrupted packet will be downloaded. Therefore - * keep track that RX_STARTED is followed by RX_COMPLETE. - * - * TODO: transceivers might have 2 frame buffers, so make this optional - */ - if (pkt == NULL) { - gnrc_netif_set_rx_started(netif, false); - break; - } - - gnrc_netif_set_rx_started(netif, false); - - 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(netif); - break; - } - case NETDEV_EVENT_TX_STARTED: { - gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_UNDEF); - gnrc_netif_set_rx_started(netif, false); - break; - } - case NETDEV_EVENT_TX_COMPLETE: { - gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_SUCCESS); - gnrc_netif_set_rx_started(netif, false); - lwmac_schedule_update(netif); - break; - } - case NETDEV_EVENT_TX_NOACK: { - gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_NOACK); - gnrc_netif_set_rx_started(netif, false); - lwmac_schedule_update(netif); - break; - } - case NETDEV_EVENT_TX_MEDIUM_BUSY: { - gnrc_netif_set_tx_feedback(netif, TX_FEEDBACK_BUSY); - gnrc_netif_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 happened*/ - while (gnrc_lwmac_get_reschedule(netif)) { - lwmac_update(netif); - } -} - -static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) -{ - 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; - } - - lwmac_schedule_update(netif); - - /* Execute main state machine because something just happened*/ - while (gnrc_lwmac_get_reschedule(netif)) { - lwmac_update(netif); - } - - return 0; -} - -static void _lwmac_msg_handler(gnrc_netif_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; - } - - /* 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; - } -#if (GNRC_MAC_ENABLE_DUTYCYCLE_RECORD == 1) - case GNRC_MAC_TYPE_GET_DUTYCYCLE: { - /* Output LWMAC's radio duty-cycle ratio */ - uint64_t duty = (uint64_t) rtt_get_counter(); - duty = ((uint64_t) netif->mac.prot.lwmac.awake_duration_sum_ticks) * 100 / - (duty - (uint64_t)netif->mac.prot.lwmac.system_start_time_ticks); - printf("[LWMAC]: achieved radio duty-cycle: %u %% \n", (unsigned) duty); - break; - } -#endif - default: { - DEBUG("[LWMAC]: unknown message type 0x%04x " - "(no message handler defined)\n", msg->type); - break; - } - } - - /* Execute main state machine because something just happened*/ - while (gnrc_lwmac_get_reschedule(netif)) { - lwmac_update(netif); - } -} - -static int _lwmac_init(gnrc_netif_t *netif) -{ - netdev_t *dev; - - int res = gnrc_netif_default_init(netif); - - if (res < 0) { - return res; - } - - dev = netif->dev; - dev->event_callback = _lwmac_event_cb; - - /* RTT is used for scheduling wakeup */ - rtt_init(); - - /* 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; - dev->driver->set(dev, NETOPT_RX_START_IRQ, &enable, sizeof(enable)); - 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 = IEEE802154_LONG_ADDRESS_LEN; - dev->driver->set(dev, NETOPT_SRC_LEN, &src_len, sizeof(src_len)); - - /* Get own address from netdev */ - 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 */ - netif->mac.tx.bcast_seqnr = netif->l2addr[0]; - - /* Reset all timeouts just to be sure */ - gnrc_lwmac_reset_timeouts(netif); - - /* Start duty cycling */ - lwmac_set_state(netif, GNRC_LWMAC_START); - -#if (GNRC_MAC_ENABLE_DUTYCYCLE_RECORD == 1) - /* Start duty cycle recording */ - netif->mac.prot.lwmac.system_start_time_ticks = rtt_get_counter(); - netif->mac.prot.lwmac.last_radio_on_time_ticks = netif->mac.prot.lwmac.system_start_time_ticks; - netif->mac.prot.lwmac.awake_duration_sum_ticks = 0; - netif->mac.prot.lwmac.lwmac_info |= GNRC_LWMAC_RADIO_IS_ON; -#endif - - return res; -} diff --git a/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c b/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c deleted file mode 100644 index b51b1408a7..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/lwmac_internal.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Implementation of internal functions of LWMAC - * - * @author Daniel Krebs - * @author Shuguo Zhuo - * @} - */ - -#include -#include - -#include "periph/rtt.h" -#include "net/gnrc.h" -#include "net/gnrc/mac/mac.h" -#include "net/gnrc/lwmac/lwmac.h" -#include "include/lwmac_internal.h" -#include "net/gnrc/netif/ieee802154.h" -#include "net/netdev/ieee802154.h" - -#define ENABLE_DEBUG 0 -#include "debug.h" - -int _gnrc_lwmac_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt) -{ - netdev_t *dev = netif->dev; - netdev_ieee802154_t *state = container_of(dev, netdev_ieee802154_t, netdev); - gnrc_netif_hdr_t *netif_hdr; - const uint8_t *src, *dst = NULL; - int res = 0; - size_t 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_htols(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 */ - iolist_t iolist = { - .iol_next = (iolist_t *)pkt->next, - .iol_base = mhr, - .iol_len = (size_t)res - }; - -#ifdef MODULE_NETSTATS_L2 - if (netif_hdr->flags & - (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { - netif->stats.tx_mcast_count++; - } - else { - netif->stats.tx_unicast_count++; - } -#endif -#ifdef MODULE_GNRC_MAC - if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) { - res = csma_sender_csma_ca_send(dev, &iolist, &netif->mac.csma_conf); - } - else { - res = dev->driver->send(dev, &iolist); - } -#else - res = dev->driver->send(dev, &iolist); -#endif - - /* 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; - gnrc_pktsnip_t *lwmac_snip; - gnrc_lwmac_hdr_t *lwmac_hdr; - - assert(info != NULL); - assert(pkt != NULL); - - netif_hdr = (gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF))->data; - if (netif_hdr == NULL) { - return -1; - } - - /* Dissect LWMAC header, Every frame has header as first member */ - lwmac_hdr = (gnrc_lwmac_hdr_t *) pkt->data; - switch (lwmac_hdr->type) { - case GNRC_LWMAC_FRAMETYPE_WR: { - lwmac_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_lwmac_frame_wr_t), - GNRC_NETTYPE_LWMAC); - break; - } - case GNRC_LWMAC_FRAMETYPE_WA: { - lwmac_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_lwmac_frame_wa_t), - GNRC_NETTYPE_LWMAC); - break; - } - case GNRC_LWMAC_FRAMETYPE_DATA_PENDING: - case GNRC_LWMAC_FRAMETYPE_DATA: { - lwmac_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_lwmac_frame_data_t), - GNRC_NETTYPE_LWMAC); - break; - } - case GNRC_LWMAC_FRAMETYPE_BROADCAST: { - lwmac_snip = gnrc_pktbuf_mark(pkt, sizeof(gnrc_lwmac_frame_broadcast_t), - GNRC_NETTYPE_LWMAC); - break; - } - default: { - return -2; - } - } - - /* Memory location may have changed while marking */ - lwmac_hdr = lwmac_snip->data; - - if (lwmac_hdr->type == GNRC_LWMAC_FRAMETYPE_WA) { - /* WA is broadcast, so get dst address out of header instead of netif */ - info->dst_addr = ((gnrc_lwmac_frame_wa_t *)lwmac_hdr)->dst_addr; - } - else if (lwmac_hdr->type == GNRC_LWMAC_FRAMETYPE_WR) { - /* WR is broadcast, so get dst address out of header instead of netif */ - info->dst_addr = ((gnrc_lwmac_frame_wr_t *)lwmac_hdr)->dst_addr; - } - else if (netif_hdr->dst_l2addr_len) { - info->dst_addr.len = netif_hdr->dst_l2addr_len; - memcpy(info->dst_addr.addr, - gnrc_netif_hdr_get_dst_addr(netif_hdr), - netif_hdr->dst_l2addr_len); - } - - if (netif_hdr->src_l2addr_len) { - info->src_addr.len = netif_hdr->src_l2addr_len; - memcpy(info->src_addr.addr, - gnrc_netif_hdr_get_src_addr(netif_hdr), - netif_hdr->src_l2addr_len); - } - - info->header = lwmac_hdr; - return 0; -} - -void _gnrc_lwmac_set_netdev_state(gnrc_netif_t *netif, netopt_state_t devstate) -{ - netif->dev->driver->set(netif->dev, - NETOPT_STATE, - &devstate, - sizeof(devstate)); - -#if (GNRC_MAC_ENABLE_DUTYCYCLE_RECORD == 1) - if (devstate == NETOPT_STATE_IDLE) { - if (!(netif->mac.prot.lwmac.lwmac_info & GNRC_LWMAC_RADIO_IS_ON)) { - netif->mac.prot.lwmac.last_radio_on_time_ticks = rtt_get_counter(); - netif->mac.prot.lwmac.lwmac_info |= GNRC_LWMAC_RADIO_IS_ON; - } - return; - } - else if ((devstate == NETOPT_STATE_SLEEP) && - (netif->mac.prot.lwmac.lwmac_info & GNRC_LWMAC_RADIO_IS_ON)) { - netif->mac.prot.lwmac.radio_off_time_ticks = rtt_get_counter(); - - netif->mac.prot.lwmac.awake_duration_sum_ticks += - (netif->mac.prot.lwmac.radio_off_time_ticks - - netif->mac.prot.lwmac.last_radio_on_time_ticks); - - netif->mac.prot.lwmac.lwmac_info &= ~GNRC_LWMAC_RADIO_IS_ON; - } -#endif -} - -netopt_state_t _gnrc_lwmac_get_netdev_state(gnrc_netif_t *netif) -{ - netopt_state_t state; - - if (0 < netif->dev->driver->get(netif->dev, - NETOPT_STATE, - &state, - sizeof(state))) { - return state; - } - return -1; -} - -int _gnrc_lwmac_dispatch_defer(gnrc_pktsnip_t *buffer[], gnrc_pktsnip_t *pkt) -{ - assert(buffer != NULL); - assert(pkt != NULL); - - /* We care about speed here, so assume packet structure */ - assert(pkt->next->type == GNRC_NETTYPE_LWMAC); - assert(pkt->next->next->type == GNRC_NETTYPE_NETIF); - - gnrc_lwmac_frame_broadcast_t *bcast = NULL; - if (((gnrc_lwmac_hdr_t *)pkt->next->data)->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) { - bcast = pkt->next->data; - } - - for (unsigned i = 0; i < GNRC_MAC_DISPATCH_BUFFER_SIZE; i++) { - /* Buffer will be filled bottom-up and emptied completely so no holes */ - if (buffer[i] == NULL) { - buffer[i] = 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; - } - } - } - - DEBUG("[LWMAC] Dispatch buffer full, dropping packet\n"); - gnrc_pktbuf_release(pkt); - - return -1; -} diff --git a/sys/net/gnrc/link_layer/lwmac/rx_state_machine.c b/sys/net/gnrc/link_layer/lwmac/rx_state_machine.c deleted file mode 100644 index 8cb136d4c1..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/rx_state_machine.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Implementation of RX state machine of LWMAC protocol - * - * @author Daniel Krebs - * @author Shuguo Zhuo - * @} - */ - -#include - -#include "net/gnrc.h" -#include "net/gnrc/lwmac/lwmac.h" -#include "net/gnrc/mac/internal.h" -#include "net/gnrc/lwmac/timeout.h" -#include "include/rx_state_machine.h" -#include "include/lwmac_internal.h" - -#define ENABLE_DEBUG 0 -#include "debug.h" - -#ifndef LOG_LEVEL -/** - * @brief Default log level define - */ -#define LOG_LEVEL LOG_WARNING -#endif -#include "log.h" - -/** - * @brief Flag to track if the receiver has got a broadcast packet - */ -#define GNRC_LWMAC_RX_FOUND_BROADCAST (0x01U) - -/** - * @brief Flag to track if the receiver has got a WR packet - */ -#define GNRC_LWMAC_RX_FOUND_WR (0x02U) - -/** - * @brief Flag to track if the receiver has got a data packet - */ -#define GNRC_LWMAC_RX_FOUND_DATA (0x04U) - -static uint8_t _packet_process_in_wait_for_wr(gnrc_netif_t *netif) -{ - uint8_t rx_info = 0; - gnrc_pktsnip_t *pkt; - - assert(netif != NULL); - - while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) { - LOG_DEBUG("[LWMAC-rx] Inspecting pkt @ %p\n", pkt); - - /* Parse packet */ - gnrc_lwmac_packet_info_t info; - - if (_gnrc_lwmac_parse_packet(pkt, &info) != 0) { - LOG_DEBUG("[LWMAC-rx] Packet could not be parsed\n"); - gnrc_pktbuf_release(pkt); - continue; - } - - if (info.header->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) { - _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_lwmac_set_quit_rx(netif, true); - /* quit TX in this cycle to avoid collisions with broadcast packets */ - gnrc_lwmac_set_quit_tx(netif, true); - break; - } - - if (info.header->type != GNRC_LWMAC_FRAMETYPE_WR) { - LOG_DEBUG("[LWMAC-rx] Packet is not WR: 0x%02x\n", info.header->type); - gnrc_pktbuf_release(pkt); - continue; - } - - /* No need to keep pkt anymore */ - gnrc_pktbuf_release(pkt); - - 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_lwmac_set_quit_tx(netif, true); - continue; - } - - /* If reach here, the node gets a WR for itself. */ - /* Save source address for later addressing */ - netif->mac.rx.l2_addr = info.src_addr; - - rx_info |= GNRC_LWMAC_RX_FOUND_WR; - break; - } - - return rx_info; -} - -/* return false if send wa failed, otherwise return true */ -static bool _send_wa(gnrc_netif_t *netif) -{ - gnrc_pktsnip_t *pkt; - gnrc_pktsnip_t *pkt_lwmac; - gnrc_netif_hdr_t *nethdr_wa; - - 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(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 = 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(netif->mac.prot.lwmac.last_wakeup)) { - lwmac_hdr.current_phase = (phase_now - - _gnrc_lwmac_ticks_to_phase(netif->mac.prot.lwmac.last_wakeup)); - } - else { - lwmac_hdr.current_phase = (phase_now + - RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US)) - - _gnrc_lwmac_ticks_to_phase(netif->mac.prot.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_lwmac_set_quit_rx(netif, true); - return false; - } - pkt_lwmac = pkt; - - pkt = gnrc_pktbuf_add(pkt, NULL, - 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_lwmac_set_quit_rx(netif, true); - return false; - } - - /* We wouldn't get here if add the NETIF header had failed, so no - sanity checks needed */ - 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, 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; - netif->dev->driver->set(netif->dev, NETOPT_AUTOACK, &autoack, - sizeof(autoack)); - - /* Send WA */ - if (_gnrc_lwmac_transmit(netif, pkt) < 0) { - LOG_ERROR("ERROR: [LWMAC-rx] Send WA failed."); - gnrc_pktbuf_release(pkt); - gnrc_lwmac_set_quit_rx(netif, true); - return false; - } - - /* Enable Auto ACK again for data reception */ - autoack = NETOPT_ENABLE; - netif->dev->driver->set(netif->dev, NETOPT_AUTOACK, &autoack, - sizeof(autoack)); - - return true; -} - -static uint8_t _packet_process_in_wait_for_data(gnrc_netif_t *netif) -{ - uint8_t rx_info = 0; - gnrc_pktsnip_t *pkt; - - assert(netif != NULL); - - pkt = NULL; - - while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) { - LOG_DEBUG("[LWMAC-rx] Inspecting pkt @ %p\n", pkt); - - /* Parse packet */ - gnrc_lwmac_packet_info_t info; - - if (_gnrc_lwmac_parse_packet(pkt, &info) != 0) { - LOG_DEBUG("[LWMAC-rx] Packet could not be parsed\n"); - gnrc_pktbuf_release(pkt); - continue; - } - - if (info.header->type == GNRC_LWMAC_FRAMETYPE_BROADCAST) { - _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_lwmac_set_quit_rx(netif, true); - continue; - } - - 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(netif, GNRC_LWMAC_TIMEOUT_DATA); - gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA, CONFIG_GNRC_LWMAC_DATA_DELAY_US); - continue; - } - - 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(netif, GNRC_LWMAC_TIMEOUT_DATA); - gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_DATA, CONFIG_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(netif, GNRC_LWMAC_TIMEOUT_DATA); - rx_info |= GNRC_LWMAC_RX_FOUND_WR; - /* Push WR back to rx queue */ - gnrc_mac_queue_rx_packet(&netif->mac.rx, 0, pkt); - break; - } - - switch (info.header->type) { - case GNRC_LWMAC_FRAMETYPE_DATA: - case GNRC_LWMAC_FRAMETYPE_DATA_PENDING: { - /* Receiver gets the data packet */ - _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(netif, GNRC_LWMAC_TIMEOUT_DATA); - rx_info |= GNRC_LWMAC_RX_FOUND_DATA; - return rx_info; - } - default: { - gnrc_pktbuf_release(pkt); - } - } - } - - return rx_info; -} - -void gnrc_lwmac_rx_start(gnrc_netif_t *netif) -{ - if (netif == NULL) { - return; - } - - /* RX address should have been reset, probably not stopped then */ - assert(netif->mac.rx.l2_addr.len == 0); - - /* Don't attempt to send a WA if channel is busy to get timings right */ - netif->mac.mac_info &= ~GNRC_NETIF_MAC_INFO_CSMA_ENABLED; - netopt_enable_t csma_disable = NETOPT_DISABLE; - netif->dev->driver->set(netif->dev, NETOPT_CSMA, &csma_disable, - sizeof(csma_disable)); - - netif->mac.rx.state = GNRC_LWMAC_RX_STATE_INIT; -} - -void gnrc_lwmac_rx_stop(gnrc_netif_t *netif) -{ - if (!netif) { - return; - } - - 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_netif_t *netif) -{ - bool reschedule = false; - - if (!netif) { - return reschedule; - } - - switch (netif->mac.rx.state) { - case GNRC_LWMAC_RX_STATE_INIT: { - 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(netif); - - /* if found broadcast packet, goto rx successful */ - if (rx_info & GNRC_LWMAC_RX_FOUND_BROADCAST) { - 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"); - netif->mac.rx.rx_bad_exten_count++; - netif->mac.rx.state = GNRC_LWMAC_RX_STATE_FAILED; - reschedule = true; - break; - } - - gnrc_priority_pktqueue_flush(&netif->mac.rx.queue); - /* Found WR packet (preamble), goto next state to send WA (preamble-ACK) */ - 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(netif)) { - netif->mac.rx.state = GNRC_LWMAC_RX_STATE_FAILED; - reschedule = true; - break; - } - - 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_netif_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(netif, GNRC_LWMAC_TIMEOUT_DATA, CONFIG_GNRC_LWMAC_DATA_DELAY_US); - - _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(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 */ - netif->mac.rx.state = GNRC_LWMAC_RX_STATE_INIT; - reschedule = true; - break; - } - - /* Only timeout if no packet (presumably the expected data) is being - * received. This won't be blocked by WRs as they restart the state - * machine (see above). - */ - if (gnrc_lwmac_timeout_is_expired(netif, GNRC_LWMAC_TIMEOUT_DATA)) { - if (!gnrc_netif_get_rx_started(netif)) { - LOG_INFO("[LWMAC-rx] DATA timed out\n"); - 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(netif, GNRC_LWMAC_TIMEOUT_DATA, - CONFIG_GNRC_LWMAC_DATA_DELAY_US); - } - break; - } - - if (!(rx_info & GNRC_LWMAC_RX_FOUND_DATA)) { - LOG_DEBUG("[LWMAC-rx] No DATA yet\n"); - break; - } - - netif->mac.rx.state = GNRC_LWMAC_RX_STATE_SUCCESSFUL; - reschedule = true; - break; - } - case GNRC_LWMAC_RX_STATE_SUCCESSFUL: - case GNRC_LWMAC_RX_STATE_FAILED: { - break; - } - case GNRC_LWMAC_RX_STATE_STOPPED: { - LOG_DEBUG("[LWMAC-rx] Reception state machine is stopped\n"); - } - } - return reschedule; -} - -void gnrc_lwmac_rx_update(gnrc_netif_t *netif) -{ - /* Update until no rescheduling needed */ - 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 deleted file mode 100644 index 73e4357fa4..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/timeout.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Timeout handling of LWMAC protocol - * - * @author Daniel Krebs - * @author Shuguo Zhuo - * @} - */ - -#include -#include - -#include "net/gnrc/lwmac/timeout.h" - -#define ENABLE_DEBUG 0 -#include "debug.h" - -static const char *lwmac_timeout_names[] = { - [GNRC_LWMAC_TIMEOUT_DISABLED] = "DISABLED", - [GNRC_LWMAC_TIMEOUT_WR] = "WR", - [GNRC_LWMAC_TIMEOUT_NO_RESPONSE] = "NO_RESPONSE", - [GNRC_LWMAC_TIMEOUT_DATA] = "DATA", - [GNRC_LWMAC_TIMEOUT_WAIT_DEST_WAKEUP] = "WAIT_FOR_DEST_WAKEUP", - [GNRC_LWMAC_TIMEOUT_WAKEUP_PERIOD] = "WAKEUP_PERIOD", -}; - -static inline void _lwmac_clear_timeout(gnrc_lwmac_timeout_t *timeout) -{ - assert(timeout); - - xtimer_remove(&(timeout->timer)); - timeout->type = GNRC_LWMAC_TIMEOUT_DISABLED; -} - -/* Return index >= 0 if found, -ENONENT if not found */ -static int _lwmac_find_timeout(gnrc_lwmac_t *lwmac, gnrc_lwmac_timeout_type_t type) -{ - assert(lwmac); - - for (unsigned i = 0; i < CONFIG_GNRC_LWMAC_TIMEOUT_COUNT; i++) { - if (lwmac->timeouts[i].type == type) { - return i; - } - } - return -ENOENT; -} - -inline bool gnrc_lwmac_timeout_is_running(gnrc_netif_t *netif, - gnrc_lwmac_timeout_type_t type) -{ - assert(netif); - return (_lwmac_find_timeout(&netif->mac.prot.lwmac, type) >= 0); -} - -bool gnrc_lwmac_timeout_is_expired(gnrc_netif_t *netif, gnrc_lwmac_timeout_type_t type) -{ - assert(netif); - - int index = _lwmac_find_timeout(&netif->mac.prot.lwmac, type); - if (index >= 0) { - if (netif->mac.prot.lwmac.timeouts[index].expired) { - _lwmac_clear_timeout(&netif->mac.prot.lwmac.timeouts[index]); - } - return netif->mac.prot.lwmac.timeouts[index].expired; - } - return false; -} - -gnrc_lwmac_timeout_t *_lwmac_acquire_timeout(gnrc_netif_t *netif, - gnrc_lwmac_timeout_type_t type) -{ - assert(netif); - - if (gnrc_lwmac_timeout_is_running(netif, type)) { - return NULL; - } - - for (unsigned i = 0; i < CONFIG_GNRC_LWMAC_TIMEOUT_COUNT; i++) { - if (netif->mac.prot.lwmac.timeouts[i].type == GNRC_LWMAC_TIMEOUT_DISABLED) { - netif->mac.prot.lwmac.timeouts[i].type = type; - return &netif->mac.prot.lwmac.timeouts[i]; - } - } - return NULL; -} - -void gnrc_lwmac_timeout_make_expire(gnrc_lwmac_timeout_t *timeout) -{ - assert(timeout); - - timeout->expired = true; -} - -void gnrc_lwmac_clear_timeout(gnrc_netif_t *netif, gnrc_lwmac_timeout_type_t type) -{ - assert(netif); - - int index = _lwmac_find_timeout(&netif->mac.prot.lwmac, type); - if (index >= 0) { - _lwmac_clear_timeout(&netif->mac.prot.lwmac.timeouts[index]); - } -} - -void gnrc_lwmac_set_timeout(gnrc_netif_t *netif, - gnrc_lwmac_timeout_type_t type, - uint32_t offset) -{ - assert(netif); - - gnrc_lwmac_timeout_t *timeout; - 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), netif->pid); - } - else { - DEBUG("[LWMAC] Cannot set timeout %s, too many concurrent timeouts\n", - lwmac_timeout_names[type]); - } -} - -void gnrc_lwmac_reset_timeouts(gnrc_netif_t *netif) -{ - assert(netif); - - for (unsigned i = 0; i < CONFIG_GNRC_LWMAC_TIMEOUT_COUNT; i++) { - if (netif->mac.prot.lwmac.timeouts[i].type != GNRC_LWMAC_TIMEOUT_DISABLED) { - _lwmac_clear_timeout(&netif->mac.prot.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 deleted file mode 100644 index 31e0cde79b..0000000000 --- a/sys/net/gnrc/link_layer/lwmac/tx_state_machine.c +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Copyright (C) 2015 Daniel Krebs - * 2016 INRIA - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup net_gnrc_lwmac - * @{ - * - * @file - * @brief Implementation of TX state machine of LWMAC protocol - * - * @author Daniel Krebs - * @author Shuguo Zhuo - * @} - */ - -#include - -#include "periph/rtt.h" -#include "net/gnrc.h" -#include "net/gnrc/lwmac/lwmac.h" -#include "random.h" -#include "net/gnrc/mac/internal.h" -#include "net/gnrc/lwmac/timeout.h" -#include "include/tx_state_machine.h" -#include "include/lwmac_internal.h" - -#ifndef LOG_LEVEL -/** - * @brief Default log level define - */ -#define LOG_LEVEL LOG_WARNING -#endif -#include "log.h" - -#define ENABLE_DEBUG 0 -#include "debug.h" - -/** - * @brief Flag to track if send packet success - */ -#define GNRC_LWMAC_TX_SUCCESS (0x01U) - -/** - * @brief Flag to track if send packet fail - */ -#define GNRC_LWMAC_TX_FAIL (0x02U) - -static uint8_t _send_bcast(gnrc_netif_t *netif) -{ - assert(netif != NULL); - - uint8_t tx_info = 0; - gnrc_pktsnip_t *pkt = netif->mac.tx.packet; - bool first = false; - - 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); - 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(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 = 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"); - 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(netif->mac.tx.packet); - /* clear packet point to avoid TX retry */ - 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; - netif->dev->driver->set(netif->dev, NETOPT_AUTOACK, &autoack, - sizeof(autoack)); - first = true; - } - - 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(netif) == NETOPT_STATE_RX) { - /* save pointer to netif header */ - 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_snip; - - 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 won't be free'd */ - netif->mac.tx.packet = NULL; - tx_info |= GNRC_LWMAC_TX_FAIL; - return tx_info; - } - - /* Don't let the packet be released yet, we want to send it again */ - gnrc_pktbuf_hold(pkt, 1); - - 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(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_netif_t *netif) -{ - assert(netif != NULL); - - uint8_t tx_info = 0; - gnrc_pktsnip_t *pkt; - gnrc_pktsnip_t *pkt_lwmac; - gnrc_netif_hdr_t *nethdr; - - /* 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(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 won't be free'd */ - netif->mac.tx.packet = NULL; - tx_info |= GNRC_LWMAC_TX_FAIL; - return tx_info; - } - - /* Assemble WR */ - gnrc_lwmac_frame_wr_t wr_hdr; - wr_hdr.header.type = GNRC_LWMAC_FRAMETYPE_WR; - 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(netif->mac.tx.packet); - LOG_ERROR("ERROR: [LWMAC-tx] Memory maybe full, drop the data packet\n"); - /* clear packet point to avoid TX retry */ - netif->mac.tx.packet = NULL; - tx_info |= GNRC_LWMAC_TX_FAIL; - return tx_info; - } - - /* track the location of this lwmac_frame_wr_t header */ - pkt_lwmac = pkt; - - pkt = gnrc_pktbuf_add(pkt, NULL, sizeof(gnrc_netif_hdr_t), GNRC_NETTYPE_NETIF); - if (pkt == NULL) { - 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(netif->mac.tx.packet); - /* clear packet point to avoid TX retry */ - netif->mac.tx.packet = NULL; - tx_info |= GNRC_LWMAC_TX_FAIL; - return tx_info; - } - - /* We wouldn't get here if adding the NETIF header had failed, so no - * sanity checks needed */ - nethdr = (gnrc_netif_hdr_t *) (gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF))->data; - - /* Construct NETIF header and insert address for WR packet */ - gnrc_netif_hdr_init(nethdr, 0, 0); - - /* Send WR as broadcast*/ - nethdr->flags |= GNRC_NETIF_HDR_FLAGS_BROADCAST; - - /* Disable Auto ACK */ - netopt_enable_t autoack = NETOPT_DISABLE; - 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_lwmac_transmit(netif, pkt); - if (res < 0) { - LOG_ERROR("ERROR: [LWMAC-tx] Send WR failed."); - gnrc_pktbuf_release(pkt); - tx_info |= GNRC_LWMAC_TX_FAIL; - return tx_info; - } - - gnrc_priority_pktqueue_flush(&netif->mac.rx.queue); - return tx_info; -} - -static uint8_t _packet_process_in_wait_for_wa(gnrc_netif_t *netif) -{ - assert(netif != NULL); - - uint8_t tx_info = 0; - gnrc_pktsnip_t *pkt; - bool found_wa = false; - bool postponed = false; - bool from_expected_destination = false; - - while ((pkt = gnrc_priority_pktqueue_pop(&netif->mac.rx.queue)) != NULL) { - LOG_DEBUG("[LWMAC-tx] Inspecting pkt @ %p\n", pkt); - - /* Parse packet */ - gnrc_lwmac_packet_info_t info; - int ret = _gnrc_lwmac_parse_packet(pkt, &info); - - if (ret != 0) { - LOG_DEBUG("[LWMAC-tx] Packet could not be parsed: %i\n", ret); - gnrc_pktbuf_release(pkt); - continue; - } - - 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(netif->mac.rx.dispatch_buffer, pkt); - gnrc_mac_dispatch(&netif->mac.rx); - /* Drop pointer to it can't get released */ - pkt = NULL; - continue; - } - - /* 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, &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 won't be free'd */ - netif->mac.tx.packet = NULL; - postponed = true; - gnrc_pktbuf_release(pkt); - break; - } - - /* 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(&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 won't be free'd */ - netif->mac.tx.packet = NULL; - postponed = true; - gnrc_pktbuf_release(pkt); - break; - } - - if (info.header->type != GNRC_LWMAC_FRAMETYPE_WA) { - LOG_DEBUG("[LWMAC-tx] Packet is not WA: 0x%02x\n", info.header->type); - gnrc_pktbuf_release(pkt); - continue; - } - - if (from_expected_destination) { - /* calculate the phase of the receiver based on WA */ - 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 (netif->mac.tx.timestamp >= wa_hdr->current_phase) { - netif->mac.tx.timestamp = netif->mac.tx.timestamp - - wa_hdr->current_phase; - } - else { - netif->mac.tx.timestamp += - RTT_US_TO_TICKS(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US); - netif->mac.tx.timestamp -= wa_hdr->current_phase; - } - - uint32_t own_phase; - own_phase = _gnrc_lwmac_ticks_to_phase(netif->mac.prot.lwmac.last_wakeup); - - if (own_phase >= netif->mac.tx.timestamp) { - own_phase = own_phase - netif->mac.tx.timestamp; - } - else { - 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(CONFIG_GNRC_LWMAC_WAKEUP_INTERVAL_US - - (3 * GNRC_LWMAC_WAKEUP_DURATION_US / 2)))) { - gnrc_lwmac_set_phase_backoff(netif, true); - LOG_WARNING("WARNING: [LWMAC-tx] phase close\n"); - } - } - - /* No need to keep pkt anymore */ - gnrc_pktbuf_release(pkt); - - if (!from_expected_destination) { - LOG_DEBUG("[LWMAC-tx] Packet is not from expected destination\n"); - break; - } - - /* All checks passed so this must be a valid WA */ - gnrc_lwmac_clear_timeout(netif, GNRC_LWMAC_TIMEOUT_WR); - - found_wa = true; - break; - } - - if (postponed) { - LOG_INFO("[LWMAC-tx] Destination is talking to another node, postpone\n"); - tx_info |= GNRC_LWMAC_TX_FAIL; - return tx_info; - } - - if (!found_wa) { - LOG_DEBUG("[LWMAC-tx] No WA yet\n"); - return tx_info; - } - - /* Save newly calculated phase for destination */ - 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(&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_netif_t *netif) -{ - assert(netif != NULL); - - gnrc_pktsnip_t *pkt = netif->mac.tx.packet; - gnrc_pktsnip_t *pkt_payload; - - assert(pkt != NULL); - /* Enable Auto ACK again */ - netopt_enable_t autoack = NETOPT_ENABLE; - 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 = CONFIG_GNRC_LWMAC_DATA_CSMA_RETRIES; - netif->dev->driver->set(netif->dev, NETOPT_CSMA_RETRIES, - &csma_retries, sizeof(csma_retries)); - - netif->mac.mac_info |= GNRC_NETIF_MAC_INFO_CSMA_ENABLED; - netopt_enable_t csma_enable = NETOPT_ENABLE; - netif->dev->driver->set(netif->dev, NETOPT_CSMA, - &csma_enable, sizeof(csma_enable)); - - pkt_payload = pkt->next; - - /* Insert LWMAC header above NETIF header. The burst (consecutive) transmission - * scheme works here (sender side). If the sender finds it has pending packets - * for the receiver (and under burst limit), it sets the packet type to - * FRAMETYPE_DATA_PENDING, to notice the receiver for next incoming packet. - * 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(&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_lwmac_set_tx_continue(netif, true); - netif->mac.tx.tx_burst_count++; - } - else { - hdr.type = GNRC_LWMAC_FRAMETYPE_DATA; - 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"); - netif->mac.tx.packet->next = pkt_payload; - gnrc_pktbuf_release(netif->mac.tx.packet); - /* clear packet point to avoid TX retry */ - 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(netif) == NETOPT_STATE_RX) { - /* save pointer to netif header */ - 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_snip; - - 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 won't be free'd */ - netif->mac.tx.packet = NULL; - return false; - } - - /* Send data */ - int res = _gnrc_lwmac_transmit(netif, pkt); - if (res < 0) { - LOG_ERROR("ERROR: [LWMAC-tx] Send data failed."); - gnrc_pktbuf_release(pkt); - /* clear packet point to avoid TX retry */ - netif->mac.tx.packet = NULL; - return false; - } - - /* Packet has been released by netdev, so drop pointer */ - netif->mac.tx.packet = NULL; - - DEBUG("[LWMAC-tx]: spent %lu WR in TX\n", - (unsigned long)netif->mac.tx.wr_sent); - -#if (LWMAC_ENABLE_DUTYCYLE_RECORD == 1) - netif->mac.prot.lwmac.pkt_start_sending_time_ticks = - rtt_get_counter() - netif->mac.prot.lwmac.pkt_start_sending_time_ticks; - DEBUG("[LWMAC-tx]: pkt sending delay in TX: %lu us\n", - RTT_TICKS_TO_US(netif->mac.prot.lwmac.pkt_start_sending_time_ticks)); -#endif - - return true; -} - -void gnrc_lwmac_tx_start(gnrc_netif_t *netif, - gnrc_pktsnip_t *pkt, - gnrc_mac_tx_neighbor_t *neighbor) -{ - assert(netif != NULL); - assert(pkt != NULL); - assert(neighbor != NULL); - - if (netif->mac.tx.packet) { - LOG_WARNING("WARNING: [LWMAC-tx] Starting but tx.packet is still set\n"); - gnrc_pktbuf_release(netif->mac.tx.packet); - } - - 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) - netif->mac.prot.lwmac.pkt_start_sending_time_ticks = rtt_get_counter(); -#endif -} - -void gnrc_lwmac_tx_stop(gnrc_netif_t *netif) -{ - assert(netif != NULL); - - 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 (netif->mac.tx.packet) { - if (netif->mac.tx.tx_retry_count >= CONFIG_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 { - netif->mac.tx.tx_retry_count++; - return; - } - } - - 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_netif_t *netif) -{ - assert(netif != NULL); - - bool reschedule = false; - - switch (netif->mac.tx.state) { - case GNRC_LWMAC_TX_STATE_INIT: { - 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(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 won't be free'd */ - 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(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 = CONFIG_GNRC_LWMAC_BROADCAST_CSMA_RETRIES; - netif->dev->driver->set(netif->dev, NETOPT_CSMA_RETRIES, - &csma_retries, sizeof(csma_retries)); - netif->mac.mac_info |= GNRC_NETIF_MAC_INFO_CSMA_ENABLED; - netopt_enable_t csma_enable = NETOPT_ENABLE; - netif->dev->driver->set(netif->dev, NETOPT_CSMA, - &csma_enable, sizeof(csma_enable)); - - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SEND_BROADCAST; - reschedule = true; - break; - } - else { - /* Use CSMA for the first WR */ - netif->mac.mac_info |= GNRC_NETIF_MAC_INFO_CSMA_ENABLED; - netopt_enable_t csma_disable = NETOPT_ENABLE; - 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(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE, GNRC_LWMAC_PREAMBLE_DURATION_US); - - 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(netif); - - if (tx_info & GNRC_LWMAC_TX_SUCCESS) { - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SUCCESSFUL; - reschedule = true; - break; - } - - if (tx_info & GNRC_LWMAC_TX_FAIL) { - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - - break; - } - 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(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) { - LOG_WARNING("WARNING: [LWMAC-tx] No response from destination, " - "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(netif); - - if (tx_info & GNRC_LWMAC_TX_FAIL) { - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_WAIT_WR_SENT; - reschedule = false; - break; - } - case GNRC_LWMAC_TX_STATE_WAIT_WR_SENT: { - 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(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) { - LOG_WARNING("WARNING: [LWMAC-tx] No response from destination\n"); - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - - if (gnrc_netif_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_netif_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 */ - netif->mac.tx.packet = NULL; - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - - if (netif->mac.tx.wr_sent == 0) { - /* Only the first WR use CSMA */ - netif->mac.mac_info &= ~GNRC_NETIF_MAC_INFO_CSMA_ENABLED; - netopt_enable_t csma_disable = NETOPT_DISABLE; - netif->dev->driver->set(netif->dev, NETOPT_CSMA, - &csma_disable, sizeof(csma_disable)); - } - - netif->mac.tx.wr_sent++; - - /* Set timeout for next WR in case no WA will be received */ - gnrc_lwmac_set_timeout(netif, GNRC_LWMAC_TIMEOUT_WR, - CONFIG_GNRC_LWMAC_TIME_BETWEEN_WR_US); - - /* Debug WR timing */ - LOG_DEBUG("[LWMAC-tx] Destination phase was: %" PRIu32 "\n", - netif->mac.tx.current_neighbor->phase); - LOG_DEBUG("[LWMAC-tx] Phase when sent was: %" PRIu32 "\n", - _gnrc_lwmac_ticks_to_phase(netif->mac.tx.timestamp)); - LOG_DEBUG("[LWMAC-tx] Ticks when sent was: %" PRIu32 "\n", - 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(netif, GNRC_LWMAC_TIMEOUT_NO_RESPONSE)) { - LOG_WARNING("WARNING: [LWMAC-tx] No response from destination\n"); - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - netif->mac.tx.preamble_fail_counts++; - break; - } - - 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_lwmac_get_tx_continue(netif)) { - LOG_DEBUG("[LWMAC-tx] Tx burst fail\n"); - 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 won't be free'd */ - netif->mac.tx.packet = NULL; - - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - else { - /* If this is the first transmission to the receiver for locating the - * latter's wake-up period, the sender just keep sending WRs until it - * finds the WA. - */ - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SEND_WR; - reschedule = true; - break; - } - } - - 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(netif); - - if (tx_info & GNRC_LWMAC_TX_FAIL) { - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - - if (tx_info & GNRC_LWMAC_TX_SUCCESS) { - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SEND_DATA; - reschedule = true; - netif->mac.tx.preamble_fail_counts = 0; - break; - } - else { - /* No WA yet */ - break; - } - } - case GNRC_LWMAC_TX_STATE_SEND_DATA: { - LOG_DEBUG("[LWMAC-tx] GNRC_LWMAC_TX_STATE_SEND_DATA\n"); - - if (!_send_data(netif)) { - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - - 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(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_netif_get_tx_feedback(netif) == TX_FEEDBACK_UNDEF) { - break; - } - else if (gnrc_netif_get_tx_feedback(netif) == TX_FEEDBACK_SUCCESS) { - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_SUCCESSFUL; - reschedule = true; - break; - } - else if (gnrc_netif_get_tx_feedback(netif) == TX_FEEDBACK_NOACK) { - LOG_ERROR("ERROR: [LWMAC-tx] Not ACKED\n"); - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - else if (gnrc_netif_get_tx_feedback(netif) == TX_FEEDBACK_BUSY) { - LOG_ERROR("ERROR: [LWMAC-tx] Channel busy \n"); - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - - LOG_ERROR("ERROR: [LWMAC-tx] Tx feedback unhandled: %i\n", - gnrc_netif_get_tx_feedback(netif)); - netif->mac.tx.state = GNRC_LWMAC_TX_STATE_FAILED; - reschedule = true; - break; - } - case GNRC_LWMAC_TX_STATE_SUCCESSFUL: - case GNRC_LWMAC_TX_STATE_FAILED: { - break; - } - case GNRC_LWMAC_TX_STATE_STOPPED: { - LOG_DEBUG("[LWMAC-tx] Transmission state machine is stopped\n"); - } - } - - return reschedule; -} - -void gnrc_lwmac_tx_update(gnrc_netif_t *netif) -{ - /* Update until no rescheduling needed */ - while (_lwmac_tx_update(netif)) {} -} diff --git a/sys/net/gnrc/link_layer/mac/internal.c b/sys/net/gnrc/link_layer/mac/internal.c index f7afb89861..edf9fd29ef 100644 --- a/sys/net/gnrc/link_layer/mac/internal.c +++ b/sys/net/gnrc/link_layer/mac/internal.c @@ -242,18 +242,6 @@ void gnrc_mac_dispatch(gnrc_mac_rx_t *rx) for (unsigned i = 0; i < GNRC_MAC_DISPATCH_BUFFER_SIZE; i++) { if (rx->dispatch_buffer[i]) { -#ifdef MODULE_GNRC_LWMAC - /* save pointer to netif header */ - gnrc_pktsnip_t *netif = rx->dispatch_buffer[i]->next->next; - - /* remove lwmac header */ - rx->dispatch_buffer[i]->next->next = NULL; - gnrc_pktbuf_release(rx->dispatch_buffer[i]->next); - - /* make append netif header after payload again */ - rx->dispatch_buffer[i]->next = netif; -#endif - if (!gnrc_netapi_dispatch_receive(rx->dispatch_buffer[i]->type, GNRC_NETREG_DEMUX_CTX_ALL, rx->dispatch_buffer[i])) { diff --git a/sys/net/gnrc/netif/init_devs/auto_init_at86rf215.c b/sys/net/gnrc/netif/init_devs/auto_init_at86rf215.c index 5ebb291a4a..b26967a800 100644 --- a/sys/net/gnrc/netif/init_devs/auto_init_at86rf215.c +++ b/sys/net/gnrc/netif/init_devs/auto_init_at86rf215.c @@ -22,9 +22,6 @@ #include "log.h" #include "board.h" #include "net/gnrc/netif/ieee802154.h" -#ifdef MODULE_GNRC_LWMAC -#include "net/gnrc/lwmac/lwmac.h" -#endif #include "net/gnrc.h" #include "include/init_devs.h" @@ -55,15 +52,7 @@ static inline void _setup_netif(gnrc_netif_t *netif, void* netdev, void* stack, if (netif == NULL || netdev == NULL) { return; } -#if defined(MODULE_GNRC_LWMAC) - gnrc_netif_lwmac_create(netif, stack, - AT86RF215_MAC_STACKSIZE, - prio, name, netdev); -#else - gnrc_netif_ieee802154_create(netif, stack, - AT86RF215_MAC_STACKSIZE, - prio, name, netdev); -#endif + gnrc_netif_ieee802154_create(netif, stack, AT86RF215_MAC_STACKSIZE, prio, name, netdev); } void auto_init_at86rf215(void) diff --git a/sys/net/gnrc/netif/init_devs/auto_init_at86rf2xx.c b/sys/net/gnrc/netif/init_devs/auto_init_at86rf2xx.c index a5ee2d52f7..ea6e8fdfa8 100644 --- a/sys/net/gnrc/netif/init_devs/auto_init_at86rf2xx.c +++ b/sys/net/gnrc/netif/init_devs/auto_init_at86rf2xx.c @@ -20,9 +20,6 @@ #include "log.h" #include "board.h" #include "net/gnrc/netif/ieee802154.h" -#ifdef MODULE_GNRC_LWMAC -#include "net/gnrc/lwmac/lwmac.h" -#endif #include "net/gnrc.h" #include "include/init_devs.h" @@ -50,17 +47,10 @@ void auto_init_at86rf2xx(void) LOG_DEBUG("[auto_init_netif] initializing at86rf2xx #%u\n", i); at86rf2xx_setup(&at86rf2xx_devs[i], &at86rf2xx_params[i], i); -#if defined(MODULE_GNRC_LWMAC) - gnrc_netif_lwmac_create(&_netif[i], _at86rf2xx_stacks[i], - AT86RF2XX_MAC_STACKSIZE, - AT86RF2XX_MAC_PRIO, "at86rf2xx-lwmac", - &at86rf2xx_devs[i].netdev.netdev); -#else gnrc_netif_ieee802154_create(&_netif[i], _at86rf2xx_stacks[i], AT86RF2XX_MAC_STACKSIZE, AT86RF2XX_MAC_PRIO, "at86rf2xx", &at86rf2xx_devs[i].netdev.netdev); -#endif } } /** @} */ diff --git a/sys/net/gnrc/netif/init_devs/auto_init_kw41zrf.c b/sys/net/gnrc/netif/init_devs/auto_init_kw41zrf.c index f9e637ef98..0cdbfe6316 100644 --- a/sys/net/gnrc/netif/init_devs/auto_init_kw41zrf.c +++ b/sys/net/gnrc/netif/init_devs/auto_init_kw41zrf.c @@ -24,10 +24,6 @@ #include "net/gnrc/netif/ieee802154.h" #include "include/init_devs.h" -#ifdef MODULE_GNRC_LWMAC -#include "net/gnrc/lwmac/lwmac.h" -#endif - #include "kw41zrf.h" /** @@ -56,15 +52,9 @@ void auto_init_kw41zrf(void) LOG_DEBUG("[auto_init_netif] initializing kw41zrf #%u\n", i); kw41zrf_setup(&kw41zrf_devs[i], i); -#if defined(MODULE_GNRC_LWMAC) - gnrc_netif_lwmac_create(&_netif[i], _kw41zrf_stacks[i], KW41ZRF_NETIF_STACKSIZE, - KW41ZRF_NETIF_PRIO, "kw41zrf-lwmac", - &kw41zrf_devs[i].netdev.netdev); -#else gnrc_netif_ieee802154_create(&_netif[i], _kw41zrf_stacks[i], KW41ZRF_NETIF_STACKSIZE, KW41ZRF_NETIF_PRIO, "kw41zrf", &kw41zrf_devs[i].netdev.netdev); -#endif } } /** @} */ diff --git a/sys/ztimer/Makefile.include b/sys/ztimer/Makefile.include index a0d0112a5d..7cb9e0f08a 100644 --- a/sys/ztimer/Makefile.include +++ b/sys/ztimer/Makefile.include @@ -4,7 +4,7 @@ ifneq (,$(filter ztimer_xtimer_compat,$(USEMODULE))) PSEUDOMODULES += xtimer endif -MODULES_ZTIMER_ON_RTT_CONFLICT = rtt_rtc gnrc_lwmac +MODULES_ZTIMER_ON_RTT_CONFLICT = rtt_rtc # By defaul use highest possible RTT_FREQUENCY for platforms that allow it. This # might not be the most optimized for conversion guarantees that ztimer_periph_rtt diff --git a/tests/net/gnrc_lwmac/Makefile b/tests/net/gnrc_lwmac/Makefile deleted file mode 100644 index b97e1268a8..0000000000 --- a/tests/net/gnrc_lwmac/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -# use samr21-xpro as default: -BOARD ?= samr21-xpro -include ../Makefile.net_common - -# Currently, LWMAC is only tested and evaluated through on samr21-xpro. -# Once LWMAC has also been tested through on other boards, the whitelist should -# be then accordingly extended. -BOARD_WHITELIST := samr21-xpro - -# Modules to include: -USEMODULE += shell -USEMODULE += shell_cmds_default -USEMODULE += ps -# Use modules for networking -# gnrc is a meta module including all required, basic gnrc networking modules -USEMODULE += gnrc -# use the default network interface for the board -USEMODULE += netdev_default -# automatically initialize the network interface -USEMODULE += auto_init_gnrc_netif -# shell command to send L2 packets with a simple string -USEMODULE += gnrc_txtsnd -# the application dumps received packets to stdout -USEMODULE += gnrc_pktdump -# Use LWMAC -USEMODULE += gnrc_lwmac - -include $(RIOTBASE)/Makefile.include - -# We use only the lower layers of the GNRC network stack, hence, we can -# reduce the size of the packet buffer a bit -# Set GNRC_PKTBUF_SIZE via CFLAGS if not being set via Kconfig. -ifndef CONFIG_GNRC_PKTBUF_SIZE - CFLAGS += -DCONFIG_GNRC_PKTBUF_SIZE=512 -endif - -# Set a custom channel if needed -include $(RIOTMAKE)/default-radio-settings.inc.mk diff --git a/tests/net/gnrc_lwmac/README.md b/tests/net/gnrc_lwmac/README.md deleted file mode 100644 index 98c45e04d3..0000000000 --- a/tests/net/gnrc_lwmac/README.md +++ /dev/null @@ -1,53 +0,0 @@ -LWMAC test application -====================== -This application is a showcase for testing LWMAC communications. Using it -for your board, you should be able to interactively use any hardware -that is supported for communications among devices based on LWMAC. - -Usage -===== - -Build, flash and start the application: -``` -export BOARD=your_board -make -make flash -make term -``` - -The `term` make target starts a terminal emulator for your board. It -connects to a default port so you can interact with the shell, usually -that is `/dev/ttyUSB0`. If your port is named differently, the -`PORT=/dev/yourport` variable can be used to override this. - - -Example output -============== - -The `ifconfig` command will help you to configure all available network -interfaces. On an samr21 board it will print something like: -``` -2015-09-16 16:58:37,762 - INFO # ifconfig -2015-09-16 16:58:37,766 - INFO # Iface 4 HWaddr: 9e:72 Channel: 26 NID: 0x23 TX-Power: 0dBm State: IDLE CSMA Retries: 4 -2015-09-16 16:58:37,768 - INFO # Long HWaddr: 36:32:48:33:46:da:9e:72 -2015-09-16 16:58:37,769 - INFO # AUTOACK CSMA -2015-09-16 16:58:37,770 - INFO # Source address length: 2 -``` - -The `txtsnd` command allows you to send a simple string directly over the link -layer (here, it is LWMAC) using unicast or broadcast. The application will also automatically print -information about any received packet over the serial. This will look like: -``` -2015-09-16 16:59:29,187 - INFO # PKTDUMP: data received: -2015-09-16 16:59:29,189 - INFO # ~~ SNIP 0 - size: 28 byte, type: -NETTYPE_UNDEF (0) -2015-09-16 16:59:29,190 - INFO # 000000 7b 3b 3a 02 85 00 e7 fb 00 00 00 00 01 -02 5a 55 -2015-09-16 16:59:29,192 - INFO # 000010 40 42 3e 62 f2 1a 00 00 00 00 00 00 -2015-09-16 16:59:29,194 - INFO # ~~ SNIP 1 - size: 18 byte, type: -NETTYPE_NETIF (-1) -2015-09-16 16:59:29,195 - INFO # if_pid: 4 rssi: 49 lqi: 78 -2015-09-16 16:59:29,196 - INFO # src_l2addr: 5a:55:40:42:3e:62:f2:1a -2015-09-16 16:59:29,197 - INFO # dst_l2addr: ff:ff -2015-09-16 16:59:29,198 - INFO # ~~ PKT - 2 snips, total size: 46 byte -``` diff --git a/tests/net/gnrc_lwmac/main.c b/tests/net/gnrc_lwmac/main.c deleted file mode 100644 index 2451b0367c..0000000000 --- a/tests/net/gnrc_lwmac/main.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008, 2009, 2010 Kaspar Schleiser - * Copyright (C) 2013 INRIA - * Copyright (C) 2013 Ludwig Knüpfer - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup tests - * @{ - * - * @file - * @brief Test application for testing the LWMAC implementation - * - * @author Kaspar Schleiser - * @author Oliver Hahm - * @author Ludwig Knüpfer - * @author Shuguo Zhuo - * - * @} - */ - -#include -#include - -#include "thread.h" -#include "shell.h" - -#include "net/gnrc/pktdump.h" -#include "net/gnrc.h" - -int main(void) -{ - puts("LWMAC test application"); - - gnrc_netreg_entry_t dump = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, - gnrc_pktdump_pid); - gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &dump); - - char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); - - return 0; -}