diff --git a/Makefile.dep b/Makefile.dep index 93d5761d415793d50e3a29732773f2c6f6a4fdba..8f1cf4a16005d64531a869321332e21f593ca94d 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -10,6 +10,11 @@ ifneq (,$(filter ccn-lite,$(USEPKG))) export CFLAGS += -DCCNL_RIOT endif +ifneq (,$(filter csma_sender,$(USEMODULE))) + USEMODULE += random + USEMODULE += xtimer +endif + ifneq (,$(filter nhdp,$(USEMODULE))) USEMODULE += conn_udp USEMODULE += xtimer diff --git a/sys/Makefile b/sys/Makefile index c6ffeb132adcf37a81149fbc754ef80f26c9d6e9..6f53b2bdaa05811b6b37a44e293c4aa90193a992 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -1,3 +1,6 @@ +ifneq (,$(filter csma_sender,$(USEMODULE))) + DIRS += net/link_layer/csma_sender +endif ifneq (,$(filter posix_semaphore,$(USEMODULE))) DIRS += posix/semaphore endif diff --git a/sys/include/net/gnrc/csma_sender.h b/sys/include/net/csma_sender.h similarity index 55% rename from sys/include/net/gnrc/csma_sender.h rename to sys/include/net/csma_sender.h index 7612c6a276a34080b76a151fdeb745a36be3f919..6faed9db60f12481cbfcc70a48702dabf62e74c9 100644 --- a/sys/include/net/gnrc/csma_sender.h +++ b/sys/include/net/csma_sender.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 INRIA + * Copyright (C) 2016 Freie Universität 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 @@ -7,8 +8,8 @@ */ /** - * @defgroup net_gnrc_csma_sender Helper interface to send packets via CSMA/CA - * @ingroup net_gnrc + * @defgroup net_csma_sender CSMA/CA helper + * @ingroup net * @brief This interface allows code from layer 2 (MAC) or higher * to send packets with CSMA/CA, whatever the abilities and/or * configuration of a given radio transceiver device are. @@ -18,75 +19,78 @@ * @brief Interface definition for the CSMA/CA helper * * @author KÊvin Roussel <Kevin.Roussel@inria.fr> + * @author Martine Lenders <mlenders@inf.fu-berlin.de> */ -#ifndef GNRC_CSMA_SENDER_H_ -#define GNRC_CSMA_SENDER_H_ +#ifndef CSMA_SENDER_H_ +#define CSMA_SENDER_H_ -#include "kernel.h" -#include "net/gnrc.h" +#include <stdint.h> + +#include "net/netdev2.h" #ifdef __cplusplus extern "C" { #endif - /** * @brief Default Minimal CSMA/CA Backoff Exponent */ -#define MAC_MIN_BE_DEFAULT (3U) +#ifndef CSMA_SENDER_MIN_BE_DEFAULT +#define CSMA_SENDER_MIN_BE_DEFAULT (3U) +#endif /** * @brief Default Maximal CSMA/CA Backoff Exponent */ -#define MAC_MAX_BE_DEFAULT (5U) +#ifndef CSMA_SENDER_MAX_BE_DEFAULT +#define CSMA_SENDER_MAX_BE_DEFAULT (5U) +#endif /** * @brief Default Maximal number of retries for sending * a given packet with the CSMA/CA method */ -#define MAC_MAX_CSMA_BACKOFFS_DEFAULT (4U) +#ifndef CSMA_SENDER_MAX_BACKOFFS_DEFAULT +#define CSMA_SENDER_MAX_BACKOFFS_DEFAULT (4U) +#endif /** * @brief CSMA/CA backoff period, in microseconds */ -#define A_UNIT_BACKOFF_PERIOD_MICROSEC (320U) - -/** - * @brief Define a different (non-standard) value for - * the CSMA macMinBE parameter. - * - * @param[in] val new value for macMinBE - */ -void set_csma_mac_min_be(uint8_t val); +#ifndef CSMA_SENDER_BACKOFF_PERIOD_UNIT +#define CSMA_SENDER_BACKOFF_PERIOD_UNIT (320U) +#endif /** - * @brief Define a different (non-standard) value for - * the CSMA macMaxBE parameter. - * - * @param[in] val new value for macMaxBE + * @brief Configuration type for backoff */ -void set_csma_mac_max_be(uint8_t val); +typedef struct { + uint8_t min_be; /**< minimum backoff exponent */ + uint8_t max_be; /**< maximum backoff exponent */ + uint16_t max_backoffs; /**< maximum number of retries */ + uint32_t backoff_period; /**< backoff period in microseconds */ +} csma_sender_conf_t; /** - * @brief Define a different (non-standard) value for - * the CSMA macMaxCSMABackoffs parameter. - * - * @param[in] val new value for macMaxCSMABackoffs + * @brief Default configuration. */ -void set_csma_mac_max_csma_backoffs(uint8_t val); +extern const csma_sender_conf_t CSMA_SENDER_CONF_DEFAULT; /** * @brief Sends a 802.15.4 frame using the CSMA/CA method * + * @pre `dev != NULL` + * * If the transceiver can (and is configured to) do hardware-assisted * CSMA/CA, this feature is used. Otherwise, a software procedure is used. * * @param[in] dev netdev device, needs to be already initialized - * @param[in] pkt pointer to the data in the packet buffer; - * it must be a complete 802.15.4-compliant frame, - * ready to be sent to the radio transceiver + * @param[in] vector pointer to the data + * @param[in] count number of elements in @p vector + * @param[in] conf configuration for the backoff; + * will be set to @ref CSMA_SENDER_CONF_DEFAULT if NULL. * * @return number of bytes that were actually send out * @return -ENODEV if @p dev is invalid @@ -97,23 +101,28 @@ void set_csma_mac_max_csma_backoffs(uint8_t val); * @return -EBUSY if radio medium never was available * to send the given data */ -int csma_ca_send(gnrc_netdev_t *dev, gnrc_pktsnip_t *pkt); +int csma_sender_csma_ca_send(netdev2_t *dev, struct iovec *vector, + unsigned count, const csma_sender_conf_t *conf); /** * @brief Sends a 802.15.4 frame when medium is avaiable. * + * @pre `dev != NULL` + * * This function is useful for sending packets without the whole CSMA/CA - * procedure, but *after* ensuring medium is available, that is : - * after a successful CCA. <br/> - * It is especially useful for broadcasting specific packets, - * like beacons; or for many sending packets in burst. <br/> - * ATTENTION: It only tries to send the given data once. If you want the - * complete CSMA/CA procedure with retries, use @c csma_ca_send(). + * procedure, but *after* ensuring medium is available, that is after a + * successful CCA. + * + * It is especially useful for broadcasting specific packets, like beacons; or + * for many sending packets in burst. + * + * @warning **ATTENTION:** It only tries to send the given data once. If you + * want the complete CSMA/CA procedure with retries, use + * @ref csma_sender_csma_ca_send(). * * @param[in] dev netdev device, needs to be already initialized - * @param[in] pkt pointer to the data in the packet buffer; - * it must be a complete 802.15.4-compliant frame, - * ready to be sent to the radio transceiver + * @param[in] vector pointer to the data + * @param[in] count number of elements in @p vector * * @return number of bytes that were actually send out * @return -ENODEV if @p dev is invalid @@ -124,13 +133,13 @@ int csma_ca_send(gnrc_netdev_t *dev, gnrc_pktsnip_t *pkt); * @return -EBUSY if radio medium was not available * to send the given data */ -int cca_send(gnrc_netdev_t *dev, gnrc_pktsnip_t *pkt); +int csma_sender_cca_send(netdev2_t *dev, struct iovec *vector, unsigned count); #ifdef __cplusplus } #endif -#endif /* GNRC_CSMA_SENDER_H_ */ +#endif /* CSMA_SENDER_H_ */ /** @} */ diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile index d011157b43f1bb4ff7380371517cec1fe6f9f4a1..a4b69955ff01a060914103bb24ed56087544e2ad 100644 --- a/sys/net/gnrc/Makefile +++ b/sys/net/gnrc/Makefile @@ -7,9 +7,6 @@ endif ifneq (,$(filter gnrc_conn_udp,$(USEMODULE))) DIRS += conn/udp endif -ifneq (,$(filter gnrc_csma_sender,$(USEMODULE))) - DIRS += link_layer/csma_sender -endif ifneq (,$(filter gnrc_icmpv6,$(USEMODULE))) DIRS += network_layer/icmpv6 endif diff --git a/sys/net/gnrc/link_layer/csma_sender/Makefile b/sys/net/gnrc/link_layer/csma_sender/Makefile deleted file mode 100644 index 41589fd0826b3130ad8e9dac87823f2d448b0d35..0000000000000000000000000000000000000000 --- a/sys/net/gnrc/link_layer/csma_sender/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -MODULE = gnrc_csma_sender - -USEMODULE += xtimer -USEMODULE += random - -include $(RIOTBASE)/Makefile.base diff --git a/sys/net/link_layer/csma_sender/Makefile b/sys/net/link_layer/csma_sender/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..48422e909a47d7cd428d10fa73825060ccc8d8c2 --- /dev/null +++ b/sys/net/link_layer/csma_sender/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/gnrc/link_layer/csma_sender/gnrc_csma_sender.c b/sys/net/link_layer/csma_sender/csma_sender.c similarity index 57% rename from sys/net/gnrc/link_layer/csma_sender/gnrc_csma_sender.c rename to sys/net/link_layer/csma_sender/csma_sender.c index 44dda081064d223f7cfeb21b2a1b0d6331cc8e42..82254f883509ad4a05ec0a3f38a500572c033fe4 100644 --- a/sys/net/gnrc/link_layer/csma_sender/gnrc_csma_sender.c +++ b/sys/net/link_layer/csma_sender/csma_sender.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 INRIA + * Copyright (C) 2016 Freie Universität 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 @@ -13,19 +14,21 @@ * @brief Implementation of the CSMA/CA helper * * @author KÊvin Roussel <Kevin.Roussel@inria.fr> + * @author Martine Lenders <mlenders@inf.fu-berlin.de> * @} */ +#include <assert.h> #include <errno.h> #include <stdbool.h> -#include "kernel.h" #include "xtimer.h" #include "random.h" -#include "net/gnrc/csma_sender.h" -#include "net/gnrc.h" +#include "net/netdev2.h" #include "net/netopt.h" +#include "net/csma_sender.h" + #define ENABLE_DEBUG (0) #include "debug.h" @@ -34,16 +37,12 @@ #include <inttypes.h> #endif - -/** @brief Current value for mac_min_be parameter */ -static uint8_t mac_min_be = MAC_MIN_BE_DEFAULT; - -/** @brief Current value for mac_max_be parameter */ -static uint8_t mac_max_be = MAC_MAX_BE_DEFAULT; - -/** @brief Current value for mac_max_csma_backoffs parameter */ -static uint8_t mac_max_csma_backoffs = MAC_MAX_CSMA_BACKOFFS_DEFAULT; - +const csma_sender_conf_t CSMA_SENDER_CONF_DEFAULT = { + CSMA_SENDER_MIN_BE_DEFAULT, + CSMA_SENDER_MAX_BE_DEFAULT, + CSMA_SENDER_MAX_BACKOFFS_DEFAULT, + CSMA_SENDER_BACKOFF_PERIOD_UNIT +}; /*--------------------- "INTERNAL" UTILITY FUNCTIONS ---------------------*/ @@ -55,19 +54,20 @@ static uint8_t mac_max_csma_backoffs = MAC_MAX_CSMA_BACKOFFS_DEFAULT; * * @return An adequate random backoff exponent in microseconds */ -static inline uint32_t choose_backoff_period(int be) +static inline uint32_t choose_backoff_period(int be, + const csma_sender_conf_t *conf) { - if (be < mac_min_be) { - be = mac_min_be; + if (be < conf->min_be) { + be = conf->min_be; } - if (be > mac_max_be) { - be = mac_max_be; + if (be > conf->max_be) { + be = conf->max_be; } - uint32_t max_backoff = ((1 << be) - 1) * A_UNIT_BACKOFF_PERIOD_MICROSEC; + uint32_t max_backoff = ((1 << be) - 1) * CSMA_SENDER_BACKOFF_PERIOD_UNIT; - uint32_t period = genrand_uint32() % max_backoff; - if (period < A_UNIT_BACKOFF_PERIOD_MICROSEC) { - period = A_UNIT_BACKOFF_PERIOD_MICROSEC; + uint32_t period = random_uint32() % max_backoff; + if (period < CSMA_SENDER_BACKOFF_PERIOD_UNIT) { + period = CSMA_SENDER_BACKOFF_PERIOD_UNIT; } return period; @@ -78,17 +78,17 @@ static inline uint32_t choose_backoff_period(int be) * @brief Perform a CCA and send the given packet if medium is available * * @param[in] device netdev device, needs to be already initialized - * @param[in] data pointer to the data in the packet buffer; - * it must be a complete 802.15.4-compliant frame, - * ready to be sent to the radio transceiver + * @param[in] vector pointer to the data + * @param[in] count number of elements in @p vector * - * @return the return value of device driver's @c send_data() - * function if medium was avilable - * @return -ECANCELED if an internal driver error occured + * @return the return value of device driver's + * netdev2_driver_t::send() function if medium was + * available + * @return -ECANCELED if an internal driver error occurred * @return -EBUSY if radio medium was not available * to send the given data */ -static int send_if_cca(gnrc_netdev_t *device, gnrc_pktsnip_t *data) +static int send_if_cca(netdev2_t *device, struct iovec *vector, unsigned count) { netopt_enable_t hwfeat; @@ -107,7 +107,7 @@ static int send_if_cca(gnrc_netdev_t *device, gnrc_pktsnip_t *data) /* if medium is clear, send the packet and return */ if (hwfeat == NETOPT_ENABLE) { DEBUG("csma: Radio medium available: sending packet.\n"); - return device->driver->send_data(device, data); + return device->driver->send(device, vector, count); } /* if we arrive here, medium was not available for transmission */ @@ -117,72 +117,64 @@ static int send_if_cca(gnrc_netdev_t *device, gnrc_pktsnip_t *data) /*------------------------- "EXPORTED" FUNCTIONS -------------------------*/ -void set_csma_mac_min_be(uint8_t val) -{ - mac_min_be = val; -} - -void set_csma_mac_max_be(uint8_t val) -{ - mac_max_be = val; -} - -void set_csma_mac_max_csma_backoffs(uint8_t val) -{ - mac_max_csma_backoffs = val; -} - - -int csma_ca_send(gnrc_netdev_t *dev, gnrc_pktsnip_t *pkt) +int csma_sender_csma_ca_send(netdev2_t *dev, struct iovec *vector, + unsigned count, const csma_sender_conf_t *conf) { netopt_enable_t hwfeat; + assert(dev); + /* choose default configuration if none is given */ + if (conf == NULL) { + conf = &CSMA_SENDER_CONF_DEFAULT; + } /* Does the transceiver do automatic CSMA/CA when sending? */ int res = dev->driver->get(dev, NETOPT_CSMA, (void *) &hwfeat, sizeof(netopt_enable_t)); bool ok = false; + switch (res) { - case -ENODEV: - /* invalid device pointer given */ - return -ENODEV; - case -ENOTSUP: - /* device doesn't make auto-CSMA/CA */ - break; - case -EOVERFLOW: /* (normally impossible...*/ - case -ECANCELED: - DEBUG("csma: !!! DEVICE DRIVER FAILURE! TRANSMISSION ABORTED!\n"); - /* internal driver error! */ - return -ECANCELED; - default: - ok = (hwfeat == NETOPT_ENABLE); + case -ENODEV: + /* invalid device pointer given */ + return -ENODEV; + case -ENOTSUP: + /* device doesn't make auto-CSMA/CA */ + break; + case -EOVERFLOW: /* (normally impossible...*/ + case -ECANCELED: + DEBUG("csma: !!! DEVICE DRIVER FAILURE! TRANSMISSION ABORTED!\n"); + /* internal driver error! */ + return -ECANCELED; + default: + ok = (hwfeat == NETOPT_ENABLE); } if (ok) { /* device does CSMA/CA all by itself: let it do its job */ DEBUG("csma: Network device does hardware CSMA/CA\n"); - return dev->driver->send_data(dev, pkt); + return dev->driver->send(dev, vector, count); } /* if we arrive here, then we must perform the CSMA/CA procedure ourselves by software */ - genrand_init(xtimer_now()); + random_init(xtimer_now()); DEBUG("csma: Starting software CSMA/CA....\n"); - int nb = 0, be = mac_min_be; + int nb = 0, be = conf->min_be; - while (nb <= mac_max_csma_backoffs) { + while (nb <= conf->max_be) { /* delay for an adequate random backoff period */ - uint32_t bp = choose_backoff_period(be); + uint32_t bp = choose_backoff_period(be, conf); xtimer_usleep(bp); /* try to send after a CCA */ - res = send_if_cca(dev, pkt); + res = send_if_cca(dev, vector, count); if (res >= 0) { /* TX done */ return res; - } else if (res != -EBUSY) { + } + else if (res != -EBUSY) { /* something has gone wrong, return the error code */ return res; } @@ -190,8 +182,8 @@ int csma_ca_send(gnrc_netdev_t *dev, gnrc_pktsnip_t *pkt) /* medium is busy: increment CSMA counters */ DEBUG("csma: Radio medium busy.\n"); be++; - if (be > mac_max_be) { - be = mac_max_be; + if (be > conf->max_be) { + be = conf->max_be; } nb++; /* ... and try again if we have no exceeded the retry limit */ @@ -203,41 +195,43 @@ int csma_ca_send(gnrc_netdev_t *dev, gnrc_pktsnip_t *pkt) } -int cca_send(gnrc_netdev_t *dev, gnrc_pktsnip_t *pkt) +int csma_sender_cca_send(netdev2_t *dev, struct iovec *vector, unsigned count) { netopt_enable_t hwfeat; + assert(dev); /* Does the transceiver do automatic CCA before sending? */ int res = dev->driver->get(dev, NETOPT_AUTOCCA, (void *) &hwfeat, sizeof(netopt_enable_t)); bool ok = false; + switch (res) { - case -ENODEV: - /* invalid device pointer given */ - return -ENODEV; - case -ENOTSUP: - /* device doesn't make auto-CCA */ - break; - case -EOVERFLOW: /* (normally impossible...*/ - case -ECANCELED: - /* internal driver error! */ - DEBUG("csma: !!! DEVICE DRIVER FAILURE! TRANSMISSION ABORTED!\n"); - return -ECANCELED; - default: - ok = (hwfeat == NETOPT_ENABLE); + case -ENODEV: + /* invalid device pointer given */ + return -ENODEV; + case -ENOTSUP: + /* device doesn't make auto-CCA */ + break; + case -EOVERFLOW: /* (normally impossible...*/ + case -ECANCELED: + /* internal driver error! */ + DEBUG("csma: !!! DEVICE DRIVER FAILURE! TRANSMISSION ABORTED!\n"); + return -ECANCELED; + default: + ok = (hwfeat == NETOPT_ENABLE); } if (ok) { /* device does auto-CCA: let him do its job */ DEBUG("csma: Network device does auto-CCA checking.\n"); - return dev->driver->send_data(dev, pkt); + return dev->driver->send(dev, vector, count); } /* if we arrive here, we must do CCA ourselves to see if radio medium is clear before sending */ - res = send_if_cca(dev, pkt); + res = send_if_cca(dev, vector, count); if (res == -EBUSY) { DEBUG("csma: Transmission cancelled!\n"); }