From b74ee8869b98e2ea8ab7a7031738ab0e0f79b7f7 Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Tue, 18 Jul 2017 14:39:03 +0200 Subject: [PATCH] slip: port to be used with netdev --- Makefile.dep | 4 - dist/tools/tunslip/README.md | 2 +- drivers/Makefile.dep | 4 + drivers/include/net/netdev.h | 3 +- drivers/include/slipdev.h | 95 ++++++ .../slip => drivers/slipdev}/Makefile | 2 - drivers/slipdev/slipdev.c | 222 ++++++++++++++ examples/gcoap/Makefile.slip | 2 +- .../gcoap/{slip_params.h => slipdev_params.h} | 10 +- examples/gnrc_border_router/Makefile | 2 +- examples/gnrc_border_router/README.md | 2 +- sys/auto_init/auto_init.c | 6 +- sys/auto_init/netif/auto_init_slip.c | 68 ----- sys/auto_init/netif/auto_init_slipdev.c | 69 +++++ sys/include/net/gnrc/netdev/raw.h | 43 +++ sys/include/net/gnrc/slip.h | 92 ------ sys/net/gnrc/Makefile | 3 - .../gnrc/link_layer/netdev/gnrc_netdev_raw.c | 99 +++++++ sys/net/gnrc/link_layer/slip/gnrc_slip.c | 277 ------------------ tests/slip/Makefile | 4 +- .../slip/{slip_params.h => slipdev_params.h} | 10 +- 21 files changed, 554 insertions(+), 465 deletions(-) create mode 100644 drivers/include/slipdev.h rename {sys/net/gnrc/link_layer/slip => drivers/slipdev}/Makefile (62%) create mode 100644 drivers/slipdev/slipdev.c rename examples/gcoap/{slip_params.h => slipdev_params.h} (79%) delete mode 100644 sys/auto_init/netif/auto_init_slip.c create mode 100644 sys/auto_init/netif/auto_init_slipdev.c create mode 100644 sys/include/net/gnrc/netdev/raw.h delete mode 100644 sys/include/net/gnrc/slip.h create mode 100644 sys/net/gnrc/link_layer/netdev/gnrc_netdev_raw.c delete mode 100644 sys/net/gnrc/link_layer/slip/gnrc_slip.c rename tests/slip/{slip_params.h => slipdev_params.h} (79%) diff --git a/Makefile.dep b/Makefile.dep index c44dd293fd..9992c38a1b 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -377,10 +377,6 @@ ifneq (,$(filter gnrc_pktdump,$(USEMODULE))) USEMODULE += od endif -ifneq (,$(filter gnrc_slip,$(USEMODULE))) - FEATURES_REQUIRED += periph_uart -endif - ifneq (,$(filter od,$(USEMODULE))) USEMODULE += fmt endif diff --git a/dist/tools/tunslip/README.md b/dist/tools/tunslip/README.md index 26cb27c65a..8fdad35e2b 100644 --- a/dist/tools/tunslip/README.md +++ b/dist/tools/tunslip/README.md @@ -1,7 +1,7 @@ Creating a SLIP network interface ================================= -The module `gnrc_slip` (Serial line IP) enables the RIOT network stack to +The module `slipdev` (Serial line IP) enables the RIOT network stack to communicate IP packets over the serial interface. This collection of tools originally from Contiki [1] enables Linux to interpret this data. Though there is a tool for such operations on Linux (`slattach`) it is only able to handle diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 4538360645..4c7eea3021 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -246,6 +246,10 @@ ifneq (,$(filter lsm6dsl,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter slipdev,$(USEMODULE))) + FEATURES_REQUIRED += periph_uart +endif + ifneq (,$(filter adc%1c,$(USEMODULE))) FEATURES_REQUIRED += periph_gpio FEATURES_REQUIRED += periph_i2c diff --git a/drivers/include/net/netdev.h b/drivers/include/net/netdev.h index d69e238674..47c06b4879 100644 --- a/drivers/include/net/netdev.h +++ b/drivers/include/net/netdev.h @@ -213,7 +213,8 @@ enum { NETDEV_TYPE_IEEE802154, NETDEV_TYPE_CC110X, NETDEV_TYPE_LORA, - NETDEV_TYPE_NRFMIN + NETDEV_TYPE_NRFMIN, + NETDEV_TYPE_SLIP, }; /** diff --git a/drivers/include/slipdev.h b/drivers/include/slipdev.h new file mode 100644 index 0000000000..3d10bf7f9b --- /dev/null +++ b/drivers/include/slipdev.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2015-17 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 + * directory for more details. + */ + +/** + * @defgroup drivers_slipdev SLIP network device + * @ingroup drivers_netdev + * @brief SLIP network device over @ref drivers_periph_uart + * @see [RFC 1055](https://github.com/RIOT-OS/RIOT/pull/6487) + * @{ + * + * @file + * @brief SLIP device definitions + * + * @author Martine Lenders + */ +#ifndef SLIPDEV_H +#define SLIPDEV_H + +#include + +#include "cib.h" +#include "net/netdev.h" +#include "periph/uart.h" +#include "ringbuffer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief UART buffer size used for TX and RX buffers + * + * Reduce this value if your expected traffic does not include full IPv6 MTU + * sized packets + */ +#ifndef SLIPDEV_BUFSIZE +#define SLIPDEV_BUFSIZE (1500U) +#endif + +/** + * @brief Packet FIFO size + * + * @note For GNRC it is recommended to have it the same size as the link-layer + * thread's message queue, but it MUST be of power of 2 + */ +#ifndef SLIPDEV_PKTFIFO_SIZE +#define SLIPDEV_PKTFIFO_SIZE (8U) +#endif + +/** + * @brief Configuration parameters for a slipdev + */ +typedef struct { + uart_t uart; /**< UART interface the device is connected to */ + uint32_t baudrate; /**< baudrate to use with slipdev_params_t::uart */ +} slipdev_params_t; + +/** + * @brief Device descriptor for slipdev + * + * @extends netdev_t + */ +typedef struct { + netdev_t netdev; /**< parent class */ + slipdev_params_t config; /**< configuration parameters */ + ringbuffer_t inbuf; /**< RX buffer */ + char rxmem[SLIPDEV_BUFSIZE]; /**< memory used by RX buffer */ + uint16_t pktfifo[SLIPDEV_PKTFIFO_SIZE]; /**< FIFO of sizes of fully received + * packets */ + cib_t pktfifo_idx; /**< CIB for slipdev_t::pktfifo */ + uint16_t inbytes; /**< the number of bytes received of + * a currently incoming packet */ + uint16_t inesc; /**< device previously received an escape + * byte */ +} slipdev_t; + +/** + * @brief Setup a slipdev device state + * + * @param[in] dev device descriptor + * @param[in] params parameters for device initialization + */ +void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params); + +#ifdef __cplusplus +} +#endif + +#endif /* SLIPDEV_H */ +/** @} */ diff --git a/sys/net/gnrc/link_layer/slip/Makefile b/drivers/slipdev/Makefile similarity index 62% rename from sys/net/gnrc/link_layer/slip/Makefile rename to drivers/slipdev/Makefile index f806e0e82e..48422e909a 100644 --- a/sys/net/gnrc/link_layer/slip/Makefile +++ b/drivers/slipdev/Makefile @@ -1,3 +1 @@ -MODULE = gnrc_slip - include $(RIOTBASE)/Makefile.base diff --git a/drivers/slipdev/slipdev.c b/drivers/slipdev/slipdev.c new file mode 100644 index 0000000000..80ee16e7ea --- /dev/null +++ b/drivers/slipdev/slipdev.c @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2017 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 + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders + */ + +#include +#include + +#include "log.h" +#include "slipdev.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define SLIP_END (0xc0U) +#define SLIP_ESC (0xdbU) +#define SLIP_END_ESC (0xdcU) +#define SLIP_ESC_ESC (0xddU) + +static int _send(netdev_t *dev, const struct iovec *vector, unsigned count); +static int _recv(netdev_t *dev, void *buf, size_t len, void *info); +static int _init(netdev_t *dev); +static void _isr(netdev_t *dev); +static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len); +static int _set(netdev_t *dev, netopt_t opt, const void *value, + size_t value_len); + +static const netdev_driver_t slip_driver = { + .send = _send, + .recv = _recv, + .init = _init, + .isr = _isr, + .get = _get, + .set = _set, +}; + +void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params) +{ + /* set device descriptor fields */ + memcpy(&dev->config, params, sizeof(dev->config)); + dev->inbytes = 0U; + dev->inesc = 0U; + dev->netdev.driver = &slip_driver; +} + +static inline void _add_byte_to_inbuf(slipdev_t *dev, uint8_t byte) +{ + if (ringbuffer_add_one(&dev->inbuf, byte) < 0) { + dev->inbytes++; + } +} + +static void _slip_rx_cb(void *arg, uint8_t data) +{ + slipdev_t *dev = arg; + + if ((data == SLIP_END) && (dev->netdev.event_callback != NULL)) { + int idx = cib_put(&dev->pktfifo_idx); + if (idx >= 0) { + dev->netdev.event_callback((netdev_t *)dev, NETDEV_EVENT_ISR); + dev->pktfifo[idx] = dev->inbytes; + } + else { + /* can't handover packet => dropping it */ + ringbuffer_remove(&dev->inbuf, dev->inbytes); + } + dev->inbytes = 0; + } + else if (dev->inesc) { + dev->inesc = 0U; + uint8_t actual = (data == SLIP_END_ESC) ? SLIP_END : + ((data == SLIP_ESC_ESC) ? SLIP_ESC : 0); + + switch (data) { + case SLIP_END_ESC: + case SLIP_ESC_ESC: + _add_byte_to_inbuf(dev, actual); + break; + default: + break; + } + } + else if (data == SLIP_ESC) { + dev->inesc = 1U; + } + else { + _add_byte_to_inbuf(dev, data); + } +} + +static int _init(netdev_t *netdev) +{ + slipdev_t *dev = (slipdev_t *)netdev; + + DEBUG("slipdev: initializing device %p on UART %i with baudrate %" PRIu32 "\n", + (void *)dev, dev->config.uart, dev->config.baudrate); + /* initialize buffers */ + ringbuffer_init(&dev->inbuf, dev->rxmem, sizeof(dev->rxmem)); + cib_init(&dev->pktfifo_idx, SLIPDEV_PKTFIFO_SIZE); + if (uart_init(dev->config.uart, dev->config.baudrate, _slip_rx_cb, + dev) != UART_OK) { + LOG_ERROR("slipdev: error initializing UART %i with baudrate %" PRIu32 "\n", + dev->config.uart, dev->config.baudrate); + return -ENODEV; + } + return 0; +} + +static inline void _write_byte(slipdev_t *dev, uint8_t byte) +{ + uart_write(dev->config.uart, &byte, 1); +} + +static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count) +{ + slipdev_t *dev = (slipdev_t *)netdev; + int bytes = 0; + + DEBUG("slipdev: sending vector of length %u\n", count); + for (unsigned i = 0; i < count; i++) { + uint8_t *data = vector[i].iov_base; + + for (unsigned j = 0; j < vector[i].iov_len; j++, data++) { + switch(*data) { + case SLIP_END: + /* escaping END byte*/ + _write_byte(dev, SLIP_ESC); + _write_byte(dev, SLIP_END_ESC); + break; + case SLIP_ESC: + /* escaping ESC byte*/ + _write_byte(dev, SLIP_ESC); + _write_byte(dev, SLIP_ESC_ESC); + break; + default: + _write_byte(dev, *data); + } + bytes++; + } + } + _write_byte(dev, SLIP_END); + return bytes; +} + +static int _recv(netdev_t *netdev, void *buf, size_t len, void *info) +{ + slipdev_t *dev = (slipdev_t *)netdev; + int res, idx = cib_peek(&dev->pktfifo_idx); + + (void)info; + if (idx < 0) { + return -EFAULT; + } + if (buf == NULL) { + if (len > 0) { + /* drop packet */ + cib_get(&dev->pktfifo_idx); + /* and remove data */ + res = ringbuffer_remove(&dev->inbuf, len); + } + else { + res = dev->pktfifo[idx]; + } + } + else if (len < dev->pktfifo[idx]) { + res = -ENOBUFS; + } + else { + size_t bytes = dev->pktfifo[cib_get(&dev->pktfifo_idx)]; + bytes = ringbuffer_get(&dev->inbuf, buf, bytes); + res = bytes; + } + return res; +} + +static void _isr(netdev_t *netdev) +{ + DEBUG("slipdev: handling ISR event\n"); + if (netdev->event_callback != NULL) { + DEBUG("slipdev: event handler set, issuing RX_COMPLETE event\n"); + netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE); + } +} + +static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len) +{ + (void)netdev; + (void)value; + (void)max_len; + switch (opt) { + case NETOPT_IS_WIRED: + return 1; + case NETOPT_DEVICE_TYPE: + assert(max_len == sizeof(uint16_t)); + *((uint16_t *)value) = NETDEV_TYPE_SLIP; + return sizeof(uint16_t); + default: + return -ENOTSUP; + } +} + +static int _set(netdev_t *netdev, netopt_t opt, const void *value, + size_t value_len) +{ + (void)netdev; + (void)opt; + (void)value; + (void)value_len; + return -ENOTSUP; +} + +/** @} */ diff --git a/examples/gcoap/Makefile.slip b/examples/gcoap/Makefile.slip index 6b7c6c65d9..211d909d7f 100644 --- a/examples/gcoap/Makefile.slip +++ b/examples/gcoap/Makefile.slip @@ -48,7 +48,7 @@ USEMODULE += gnrc_rpl # Border router requirements # Include SLIP package for IP over Serial communication -USEMODULE += gnrc_slip +USEMODULE += slipdev # Specify the mandatory networking modules for 6LoWPAN border router USEMODULE += gnrc_sixlowpan_border_router_default # Additional networking modules that can be dropped if not needed diff --git a/examples/gcoap/slip_params.h b/examples/gcoap/slipdev_params.h similarity index 79% rename from examples/gcoap/slip_params.h rename to examples/gcoap/slipdev_params.h index 3978ef7b82..bd3979ab0a 100644 --- a/examples/gcoap/slip_params.h +++ b/examples/gcoap/slipdev_params.h @@ -16,16 +16,16 @@ * @author Martine Lenders */ -#ifndef SLIP_PARAMS_H -#define SLIP_PARAMS_H +#ifndef SLIPDEV_PARAMS_H +#define SLIPDEV_PARAMS_H -#include "net/gnrc/slip.h" +#include "slipdev.h" #ifdef __cplusplus extern "C" { #endif -static gnrc_slip_params_t gnrc_slip_params[] = { +static slipdev_params_t slipdev_params[] = { { .uart = SLIP_UART, .baudrate = SLIP_BAUDRATE, @@ -35,5 +35,5 @@ static gnrc_slip_params_t gnrc_slip_params[] = { #ifdef __cplusplus } #endif -#endif /* SLIP_PARAMS_H */ +#endif /* SLIPDEV_PARAMS_H */ /** @} */ diff --git a/examples/gnrc_border_router/Makefile b/examples/gnrc_border_router/Makefile index c458ce0d5e..9b2df0637c 100644 --- a/examples/gnrc_border_router/Makefile +++ b/examples/gnrc_border_router/Makefile @@ -47,7 +47,7 @@ endif #CFLAGS += -DSLIP_UART=$(SLIP_UART) #CFLAGS += -DSLIP_BAUDRATE=$(SLIP_BAUDRATE) # Include SLIP package for IP over Serial communication -#USEMODULE += gnrc_slip +#USEMODULE += slipdev # Include packages that pull up and auto-init the link layer. # NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present diff --git a/examples/gnrc_border_router/README.md b/examples/gnrc_border_router/README.md index 7812dafac9..8f742f8b59 100644 --- a/examples/gnrc_border_router/README.md +++ b/examples/gnrc_border_router/README.md @@ -210,7 +210,7 @@ INCLUDES += -I$(CURDIR) CFLAGS += -DSLIP_UART=$(SLIP_UART) CFLAGS += -DSLIP_BAUDRATE=$(SLIP_BAUDRATE) # Include SLIP package for IP over Serial communication -USEMODULE += gnrc_slip +USEMODULE += slipdev ``` diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 15a4a6d348..726b673ab7 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -200,9 +200,9 @@ void auto_init(void) auto_init_ethos(); #endif -#ifdef MODULE_GNRC_SLIP - extern void auto_init_slip(void); - auto_init_slip(); +#ifdef MODULE_SLIPDEV + extern void auto_init_slipdev(void); + auto_init_slipdev(); #endif #ifdef MODULE_CC110X diff --git a/sys/auto_init/netif/auto_init_slip.c b/sys/auto_init/netif/auto_init_slip.c deleted file mode 100644 index 51f704ccae..0000000000 --- a/sys/auto_init/netif/auto_init_slip.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2015 Kaspar Schleiser - * - * 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 auto_init_gnrc_netif - * @{ - * - * @file - * @brief Auto initialization for XBee network interfaces - * - * @author Kaspar Schleiser - */ - -#ifdef MODULE_GNRC_SLIP - -#include "log.h" -#include "board.h" -#include "net/gnrc/netdev.h" -#include "net/gnrc.h" - -#include "net/gnrc/slip.h" -#include "slip_params.h" - -#define SLIP_NUM (sizeof(gnrc_slip_params)/sizeof(gnrc_slip_params_t)) - -static gnrc_slip_dev_t slip_devs[SLIP_NUM]; - -/** - * @brief Define stack parameters for the MAC layer thread - * @{ - */ -#define SLIP_STACKSIZE (THREAD_STACKSIZE_DEFAULT) -#ifndef SLIP_PRIO -#define SLIP_PRIO (GNRC_NETDEV_MAC_PRIO) -#endif - -/** - * @brief Stacks for the MAC layer threads - */ -static char _slip_stacks[SLIP_NUM][SLIP_STACKSIZE]; - -void auto_init_slip(void) -{ - for (unsigned i = 0; i < SLIP_NUM; i++) { - const gnrc_slip_params_t *p = &gnrc_slip_params[i]; - - LOG_DEBUG("[auto_init_netif] initializing slip #%u\n", i); - - kernel_pid_t res = gnrc_slip_init(&slip_devs[i], p->uart, p->baudrate, - _slip_stacks[i], SLIP_STACKSIZE, - SLIP_PRIO); - - if (res <= KERNEL_PID_UNDEF) { - LOG_ERROR("[auto_init_netif] error initializing slip #%u\n", i); - } - } -} - -#else -typedef int dont_be_pedantic; -#endif /* MODULE_GNRC_SLIP */ -/** @} */ diff --git a/sys/auto_init/netif/auto_init_slipdev.c b/sys/auto_init/netif/auto_init_slipdev.c new file mode 100644 index 0000000000..fa836b8468 --- /dev/null +++ b/sys/auto_init/netif/auto_init_slipdev.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2015 Kaspar Schleiser + * + * 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 auto_init_gnrc_netif + * @{ + * + * @file + * @brief Auto initialization for XBee network interfaces + * + * @author Kaspar Schleiser + */ + +#ifdef MODULE_SLIPDEV + +#include "log.h" +#include "board.h" +#include "net/gnrc/netdev.h" +#include "net/gnrc/netdev/raw.h" +#include "net/gnrc.h" + +#include "slipdev.h" +#include "slipdev_params.h" + +#define SLIPDEV_NUM (sizeof(slipdev_params)/sizeof(slipdev_params_t)) + +/** + * @brief Define stack parameters for the MAC layer thread + * @{ + */ +#define SLIPDEV_STACKSIZE (THREAD_STACKSIZE_DEFAULT) +#ifndef SLIPDEV_PRIO +#define SLIPDEV_PRIO (GNRC_NETDEV_MAC_PRIO) +#endif + +static slipdev_t slipdevs[SLIPDEV_NUM]; +static gnrc_netdev_t gnrc_adpt[SLIPDEV_NUM]; +static char _slipdev_stacks[SLIPDEV_NUM][SLIPDEV_STACKSIZE]; + +void auto_init_slipdev(void) +{ + for (unsigned i = 0; i < SLIPDEV_NUM; i++) { + const slipdev_params_t *p = &slipdev_params[i]; + + LOG_DEBUG("[auto_init_netif] initializing slip #%u\n", i); + + slipdev_setup(&slipdevs[i], p); + kernel_pid_t res = gnrc_netdev_raw_init(&gnrc_adpt[i], + (netdev_t *)&slipdevs[i]); + + if (res < 0) { + LOG_ERROR("[auto_init_netif] error initializing slipdev #%u\n", i); + } + else { + gnrc_netdev_init(_slipdev_stacks[i], SLIPDEV_STACKSIZE, + SLIPDEV_PRIO, "slipdev", &gnrc_adpt[i]); + } + } +} +#else +typedef int dont_be_pedantic; +#endif /* MODULE_SLIPDEV */ +/** @} */ diff --git a/sys/include/net/gnrc/netdev/raw.h b/sys/include/net/gnrc/netdev/raw.h new file mode 100644 index 0000000000..abb29520f6 --- /dev/null +++ b/sys/include/net/gnrc/netdev/raw.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2017 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 + * directory for more details. + */ + +/** + * @ingroup net_gnrc_netdev + * @{ + * + * @file + * @brief netdev gnrc raw (i.e. pure L3) glue code interface + * + * @author Martine Lenders + */ +#ifndef NET_GNRC_NETDEV_RAW_H +#define NET_GNRC_NETDEV_RAW_H + +#include "net/gnrc/netdev.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize gnrc handler for netdev raw L3 devices + * + * @param[in] gnrc_netdev gnrc_netdev struct to initialize + * @param[in] dev network device to handle + * + * @return 1 on success + * @return <=0 on error + */ +int gnrc_netdev_raw_init(gnrc_netdev_t *gnrc_netdev, netdev_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* NET_GNRC_NETDEV_RAW_H */ +/** @} */ diff --git a/sys/include/net/gnrc/slip.h b/sys/include/net/gnrc/slip.h deleted file mode 100644 index ac6d249f52..0000000000 --- a/sys/include/net/gnrc/slip.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2015 Martine Lenders - * - * 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. - */ - -/** - * @defgroup net_gnrc_slip SLIP - * @ingroup net_gnrc - * @brief Provides a SLIP interface over UART utilizing - * @ref drivers_periph_uart. - * @see RFC 1055 - * @{ - * - * @file - * @brief SLIP interface defintion - * - * @author Martine Lenders - * @author Hauke Petersen - */ - -#ifndef NET_GNRC_SLIP_H -#define NET_GNRC_SLIP_H - -#include - -#include "net/gnrc.h" -#include "periph/uart.h" -#include "ringbuffer.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief UART buffer size used for TX and RX buffers - * - * Reduce this value if your expected traffic does not include full IPv6 MTU - * sized packets - */ -#ifndef GNRC_SLIP_BUFSIZE -#define GNRC_SLIP_BUFSIZE (1500U) -#endif - -/** - * @brief Device descriptor for SLIP devices - */ -typedef struct { - uart_t uart; /**< the UART interface */ - ringbuffer_t in_buf; /**< RX buffer */ - ringbuffer_t out_buf; /**< TX buffer */ - char rx_mem[GNRC_SLIP_BUFSIZE]; /**< memory used by RX buffer */ - uint32_t in_bytes; /**< the number of bytes received of a - * currently incoming packet */ - uint16_t in_esc; /**< receiver is in escape mode */ - kernel_pid_t slip_pid; /**< PID of the device thread */ -} gnrc_slip_dev_t; - -/** - * @brief auto_init struct holding SLIP initalization params - */ -typedef struct xbee_params { - uart_t uart; /**< UART interfaced the device is connected to */ - uint32_t baudrate; /**< baudrate to use */ -} gnrc_slip_params_t; - -/** - * @brief Initializes a new @ref net_gnrc_slip control thread for UART device - * @p uart - * - * @param[in] dev un-initialized SLIP device descriptor - * @param[in] uart UART device to use - * @param[in] baudrate baudrate to use - * @param[in] stack stack memory to use for the SLIP devices thread - * @param[in] stack_size size of @p stack - * @param[in] priority priority for the newly created thread - * - * @return PID of SLIP thread on success - * @return -EFAULT, if slip thread could not be created - * @return -ENODEV, if gnrc_slip_dev_t::uart of @p dev was no valid UART - */ -kernel_pid_t gnrc_slip_init(gnrc_slip_dev_t *dev, uart_t uart, uint32_t baudrate, - char *stack, size_t stack_size, char priority); - -#ifdef __cplusplus -} -#endif - -#endif /* NET_GNRC_SLIP_H */ -/** @} */ diff --git a/sys/net/gnrc/Makefile b/sys/net/gnrc/Makefile index 28e08a942c..1d01eaa27e 100644 --- a/sys/net/gnrc/Makefile +++ b/sys/net/gnrc/Makefile @@ -118,9 +118,6 @@ endif ifneq (,$(filter gnrc_sixlowpan_netif,$(USEMODULE))) DIRS += network_layer/sixlowpan/netif endif -ifneq (,$(filter gnrc_slip,$(USEMODULE))) - DIRS += link_layer/slip -endif ifneq (,$(filter gnrc_sock,$(USEMODULE))) DIRS += sock endif diff --git a/sys/net/gnrc/link_layer/netdev/gnrc_netdev_raw.c b/sys/net/gnrc/link_layer/netdev/gnrc_netdev_raw.c new file mode 100644 index 0000000000..cecfdd089e --- /dev/null +++ b/sys/net/gnrc/link_layer/netdev/gnrc_netdev_raw.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2017 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 + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders + */ + +#include "net/gnrc/netdev/raw.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define IP_VERSION_MASK (0xf0) +#define IP_VERSION4 (0x40) +#define IP_VERSION6 (0x60) + +static gnrc_pktsnip_t *_recv(gnrc_netdev_t *gnrc_netdev) +{ + netdev_t *dev = gnrc_netdev->dev; + int bytes_expected = dev->driver->recv(dev, NULL, 0, NULL); + gnrc_pktsnip_t *pkt = NULL; + + if (bytes_expected > 0) { + int nread; + + pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF); + + if (!pkt) { + DEBUG("gnrc_netdev_raw: cannot allocate pktsnip.\n"); + /* drop packet */ + dev->driver->recv(dev, NULL, bytes_expected, NULL); + return pkt; + } + nread = dev->driver->recv(dev, pkt->data, bytes_expected, NULL); + if (nread <= 0) { + DEBUG("gnrc_netdev_raw: read error.\n"); + gnrc_pktbuf_release(pkt); + return NULL; + } + if (nread < bytes_expected) { + /* we've got less then the expected packet size, + * so free the unused space.*/ + DEBUG("gnrc_netdev_raw: reallocating.\n"); + gnrc_pktbuf_realloc_data(pkt, nread); + } + switch (((uint8_t *)pkt->data)[0] & IP_VERSION_MASK) { +#ifdef MODULE_GNRC_IPV6 + case IP_VERSION6: + pkt->type = GNRC_NETTYPE_IPV6; + break; +#endif + default: + /* leave UNDEF */ + break; + } + } + return pkt; +} + +static int _send(gnrc_netdev_t *gnrc_netdev, gnrc_pktsnip_t *pkt) +{ + gnrc_pktsnip_t *vector; + int res = -ENOBUFS; + size_t n; + + if (pkt->type == GNRC_NETTYPE_NETIF) { + /* we don't need the netif snip: remove it */ + pkt = gnrc_pktbuf_remove_snip(pkt, pkt); + } + vector = gnrc_pktbuf_get_iovec(pkt, &n); + if (vector != NULL) { + struct iovec *v = (struct iovec *)vector->data; + netdev_t *dev = gnrc_netdev->dev; + +#ifdef MODULE_NETSTATS_L2 + gnrc_netdev->dev->stats.tx_unicast_count++; +#endif + res = dev->driver->send(dev, v, n); + } + return res; +} + +int gnrc_netdev_raw_init(gnrc_netdev_t *gnrc_netdev, netdev_t *dev) +{ + gnrc_netdev->send = _send; + gnrc_netdev->recv = _recv; + gnrc_netdev->dev = dev; + + return 0; +} +/** @} */ diff --git a/sys/net/gnrc/link_layer/slip/gnrc_slip.c b/sys/net/gnrc/link_layer/slip/gnrc_slip.c deleted file mode 100644 index 3024a51d04..0000000000 --- a/sys/net/gnrc/link_layer/slip/gnrc_slip.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2015 Martine Lenders - * - * 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_slip - * @{ - * - * @file - * @brief SLIP device implementation - * - * @author Martine Lenders - * @author Hauke Petersen - * - * @} - */ - -#include -#include -#include -#include - -#include "kernel_types.h" -#include "msg.h" -#include "net/gnrc.h" -#include "periph/uart.h" -#include "od.h" -#include "ringbuffer.h" -#include "thread.h" -#include "net/ipv6/hdr.h" - -#include "net/gnrc/slip.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#define _SLIP_END ('\xc0') -#define _SLIP_ESC ('\xdb') -#define _SLIP_END_ESC ('\xdc') -#define _SLIP_ESC_ESC ('\xdd') - -#define _SLIP_MSG_TYPE (0xc1dc) /* chosen randomly */ -#define _SLIP_NAME "SLIP" -#define _SLIP_MSG_QUEUE_SIZE (8U) - -#define _SLIP_DEV(arg) ((gnrc_slip_dev_t *)arg) - -/* UART callbacks */ -static void _slip_rx_cb(void *arg, uint8_t data) -{ - if (data == (uint8_t)_SLIP_END) { - msg_t msg; - - msg.type = _SLIP_MSG_TYPE; - msg.content.value = _SLIP_DEV(arg)->in_bytes; - - msg_send_int(&msg, _SLIP_DEV(arg)->slip_pid); - - _SLIP_DEV(arg)->in_bytes = 0; - } - else if (_SLIP_DEV(arg)->in_esc) { - _SLIP_DEV(arg)->in_esc = 0; - - switch (data) { - case ((uint8_t)_SLIP_END_ESC): - if (ringbuffer_add_one(&_SLIP_DEV(arg)->in_buf, _SLIP_END) < 0) { - _SLIP_DEV(arg)->in_bytes++; - } - - break; - - case ((uint8_t)_SLIP_ESC_ESC): - if (ringbuffer_add_one(&_SLIP_DEV(arg)->in_buf, _SLIP_ESC) < 0) { - _SLIP_DEV(arg)->in_bytes++; - } - - break; - - default: - break; - } - } - else if (data == (uint8_t)_SLIP_ESC) { - _SLIP_DEV(arg)->in_esc = 1; - } - else { - if (ringbuffer_add_one(&_SLIP_DEV(arg)->in_buf, data) < 0) { - _SLIP_DEV(arg)->in_bytes++; - } - } -} - -/* SLIP receive handler */ -static void _slip_receive(gnrc_slip_dev_t *dev, size_t bytes) -{ - gnrc_pktsnip_t *pkt, *hdr; - - hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0); - if (hdr == NULL) { - DEBUG("slip: no space left in packet buffer\n"); - return; - } - - ((gnrc_netif_hdr_t *)(hdr->data))->if_pid = thread_getpid(); - - pkt = gnrc_pktbuf_add(hdr, NULL, bytes, GNRC_NETTYPE_UNDEF); - - if (pkt == NULL) { - DEBUG("slip: no space left in packet buffer\n"); - gnrc_pktbuf_release(hdr); - return; - } - - if (ringbuffer_get(&dev->in_buf, pkt->data, bytes) != bytes) { - DEBUG("slip: could not read %u bytes from ringbuffer\n", (unsigned)bytes); - gnrc_pktbuf_release(pkt); - return; - } -#if ENABLE_DEBUG && defined(MODULE_OD) - else { - DEBUG("slip: received data\n"); - od_hex_dump(pkt->data, bytes, OD_WIDTH_DEFAULT); - } -#endif - -#ifdef MODULE_GNRC_IPV6 - if ((pkt->size >= sizeof(ipv6_hdr_t)) && ipv6_hdr_is(pkt->data)) { - pkt->type = GNRC_NETTYPE_IPV6; - } -#endif - - if (gnrc_netapi_dispatch_receive(pkt->type, GNRC_NETREG_DEMUX_CTX_ALL, pkt) == 0) { - DEBUG("slip: unable to forward packet of type %i\n", pkt->type); - gnrc_pktbuf_release(pkt); - } -} - -static inline void _slip_send_char(gnrc_slip_dev_t *dev, char c) -{ - uart_write(dev->uart, (uint8_t *)&c, 1); -} - -/* SLIP send handler */ -static void _slip_send(gnrc_slip_dev_t *dev, gnrc_pktsnip_t *pkt) -{ - gnrc_pktsnip_t *ptr; - - ptr = pkt->next; /* ignore gnrc_netif_hdr_t, we don't need it */ - - while (ptr != NULL) { - DEBUG("slip: send pktsnip of length %u over UART_%d\n", (unsigned)ptr->size, dev->uart); - char *data = ptr->data; - - for (size_t i = 0; i < ptr->size; i++) { - switch (data[i]) { - case _SLIP_END: - DEBUG("slip: encountered END byte on send: stuff with ESC\n"); - _slip_send_char(dev, _SLIP_ESC); - _slip_send_char(dev, _SLIP_END_ESC); - break; - - case _SLIP_ESC: - DEBUG("slip: encountered ESC byte on send: stuff with ESC\n"); - _slip_send_char(dev, _SLIP_ESC); - _slip_send_char(dev, _SLIP_ESC_ESC); - break; - - default: - _slip_send_char(dev, data[i]); - - break; - } - } - - ptr = ptr->next; - } - - _slip_send_char(dev, _SLIP_END); - - gnrc_pktbuf_release(pkt); -} - -static inline int _slip_get(gnrc_netapi_opt_t *opt) -{ - switch (opt->opt) { - case NETOPT_IS_WIRED: - return 1; - default: - return -ENOTSUP; - } -} - -static void *_slip(void *args) -{ - gnrc_slip_dev_t *dev = _SLIP_DEV(args); - msg_t msg, reply, msg_q[_SLIP_MSG_QUEUE_SIZE]; - - msg_init_queue(msg_q, _SLIP_MSG_QUEUE_SIZE); - dev->slip_pid = thread_getpid(); - gnrc_netif_add(dev->slip_pid); - - DEBUG("slip: SLIP runs on UART_%d\n", dev->uart); - - while (1) { - DEBUG("slip: waiting for incoming messages\n"); - msg_receive(&msg); - - switch (msg.type) { - case _SLIP_MSG_TYPE: - DEBUG("slip: incoming message of size %" PRIu32 " from UART_%d in buffer\n", - msg.content.value, dev->uart); - _slip_receive(dev, (size_t)msg.content.value); - break; - - case GNRC_NETAPI_MSG_TYPE_SND: - DEBUG("slip: GNRC_NETAPI_MSG_TYPE_SND received\n"); - _slip_send(dev, msg.content.ptr); - break; - - case GNRC_NETAPI_MSG_TYPE_GET: - DEBUG("slip: GNRC_NETAPI_MSG_TYPE_GET received\n"); - reply.type = GNRC_NETAPI_MSG_TYPE_ACK; - reply.content.value = (uint32_t)_slip_get(msg.content.ptr); - msg_reply(&msg, &reply); - break; - - case GNRC_NETAPI_MSG_TYPE_SET: - DEBUG("slip: GNRC_NETAPI_MSG_TYPE_SET received\n"); - reply.type = GNRC_NETAPI_MSG_TYPE_ACK; - reply.content.value = (uint32_t)(-ENOTSUP); - DEBUG("slip: I don't support this but have to reply.\n"); - msg_reply(&msg, &reply); - break; - } - } - - /* should be never reached */ - return NULL; -} - -kernel_pid_t gnrc_slip_init(gnrc_slip_dev_t *dev, uart_t uart, uint32_t baudrate, - char *stack, size_t stack_size, char priority) -{ - kernel_pid_t pid; - - /* reset device descriptor fields */ - dev->uart = uart; - dev->in_bytes = 0; - dev->in_esc = 0; - dev->slip_pid = KERNEL_PID_UNDEF; - - /* initialize buffers */ - ringbuffer_init(&dev->in_buf, dev->rx_mem, sizeof(dev->rx_mem)); - - /* initialize UART */ - DEBUG("slip: initialize UART_%d with baudrate %" PRIu32 "\n", uart, - baudrate); - if (uart_init(uart, baudrate, _slip_rx_cb, dev) != UART_OK) { - DEBUG("slip: error initializing UART_%i with baudrate %" PRIu32 "\n", - uart, baudrate); - return -ENODEV; - } - - /* start SLIP thread */ - DEBUG("slip: starting SLIP thread\n"); - pid = thread_create(stack, stack_size, priority, THREAD_CREATE_STACKTEST, - _slip, dev, _SLIP_NAME); - if (pid < 0) { - DEBUG("slip: unable to create SLIP thread\n"); - return -EFAULT; - } - return pid; -} diff --git a/tests/slip/Makefile b/tests/slip/Makefile index a60c718745..163f6b259a 100644 --- a/tests/slip/Makefile +++ b/tests/slip/Makefile @@ -10,7 +10,9 @@ BOARD_BLACKLIST += mips-malta USEMODULE += auto_init_gnrc_netif USEMODULE += gnrc USEMODULE += gnrc_pktdump -USEMODULE += gnrc_slip +USEMODULE += gnrc_netdev +USEMODULE += gnrc_txtsnd +USEMODULE += slipdev USEMODULE += shell USEMODULE += shell_commands diff --git a/tests/slip/slip_params.h b/tests/slip/slipdev_params.h similarity index 79% rename from tests/slip/slip_params.h rename to tests/slip/slipdev_params.h index 3978ef7b82..bd3979ab0a 100644 --- a/tests/slip/slip_params.h +++ b/tests/slip/slipdev_params.h @@ -16,16 +16,16 @@ * @author Martine Lenders */ -#ifndef SLIP_PARAMS_H -#define SLIP_PARAMS_H +#ifndef SLIPDEV_PARAMS_H +#define SLIPDEV_PARAMS_H -#include "net/gnrc/slip.h" +#include "slipdev.h" #ifdef __cplusplus extern "C" { #endif -static gnrc_slip_params_t gnrc_slip_params[] = { +static slipdev_params_t slipdev_params[] = { { .uart = SLIP_UART, .baudrate = SLIP_BAUDRATE, @@ -35,5 +35,5 @@ static gnrc_slip_params_t gnrc_slip_params[] = { #ifdef __cplusplus } #endif -#endif /* SLIP_PARAMS_H */ +#endif /* SLIPDEV_PARAMS_H */ /** @} */