ng_slip: initial import

This commit is contained in:
Martine Lenders 2015-03-22 18:42:34 +01:00
parent b11eb90042
commit 96ab1fa283
6 changed files with 381 additions and 0 deletions

View File

@ -180,6 +180,10 @@ ifneq (,$(filter ng_pktdump,$(USEMODULE)))
USEMODULE += od
endif
ifneq (,$(filter ng_slip,$(USEMODULE)))
USEMODULE += ng_netbase
endif
ifneq (,$(filter aodvv2,$(USEMODULE)))
USEMODULE += vtimer
USEMODULE += sixlowpan

View File

@ -119,6 +119,9 @@ endif
ifneq (,$(filter ng_sixlowpan_netif,$(USEMODULE)))
DIRS += net/network_layer/ng_sixlowpan/netif
endif
ifneq (,$(filter ng_slip,$(USEMODULE)))
DIRS += net/link_layer/ng_slip
endif
ifneq (,$(filter netapi,$(USEMODULE)))
DIRS += net/crosslayer/netapi
endif

View File

@ -82,6 +82,10 @@ ifneq (,$(filter cpp11-compat,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/cpp11-compat/include
endif
ifneq (,$(filter ng_slip,$(USEMODULE)))
FEATURES_REQUIRED += periph_uart
endif
ifneq (,$(filter embunit,$(USEMODULE)))
ifeq ($(OUTPUT),XML)
CFLAGS += -DOUTPUT=OUTPUT_XML

85
sys/include/net/ng_slip.h Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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_ng_slip SLIP
* @ingroup net
* @brief Provides a SLIP interface over UART utilizing
* @ref driver_periph_uart.
* @see <a href="https://www.ietf.org/rfc/rfc1055">RFC 1055</a>
* @{
*
* @file
* @brief SLIP interface defintion
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef NG_SLIP_H_
#define NG_SLIP_H_
#include <inttypes.h>
#include "net/ng_netbase.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 NG_SLIP_BUFSIZE
#define NG_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[NG_SLIP_BUFSIZE]; /**< memory used by RX buffer */
char tx_mem[NG_SLIP_BUFSIZE]; /**< memory used by TX 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 */
} ng_slip_dev_t;
/**
* @brief Initializes a new @ref net_ng_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 ng_slip_dev_t::uart of @p dev was no valid UART
*/
kernel_pid_t ng_slip_init(ng_slip_dev_t *dev, uart_t uart, uint32_t baudrate,
char *stack, size_t stack_size, char priority);
#ifdef __cplusplus
}
#endif
#endif /* __SLIP_H_ */
/** @} */

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,284 @@
/*
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
*
* 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_ng_slip
* @{
*
* @file
* @brief SLIP device implementation
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*
* @}
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "kernel.h"
#include "kernel_types.h"
#include "msg.h"
#include "net/ng_netbase.h"
#include "periph/uart.h"
#include "ringbuffer.h"
#include "thread.h"
#include "net/ng_ipv6/hdr.h"
#include "net/ng_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) ((ng_slip_dev_t *)arg)
/* UART callbacks */
static void _slip_rx_cb(void *arg, char data)
{
if (data == _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;
}
if (_SLIP_DEV(arg)->in_esc) {
_SLIP_DEV(arg)->in_esc = 0;
switch (data) {
case (_SLIP_END_ESC):
if (ringbuffer_add_one(_SLIP_DEV(arg)->in_buf, _SLIP_END) < 0) {
_SLIP_DEV(arg)->in_bytes++;
}
break;
case (_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 == _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++;
}
}
}
int _slip_tx_cb(void *arg)
{
if (_SLIP_DEV(arg)->out_buf->avail > 0) {
char c = (char)ringbuffer_get_one(_SLIP_DEV(arg)->out_buf);
uart_write((uart_t)(_SLIP_DEV(arg)->uart), c);
return 1;
}
return 0;
}
/* SLIP receive handler */
static void _slip_receive(ng_slip_dev_t *dev, size_t bytes)
{
ng_netif_hdr_t *hdr;
ng_netreg_entry_t *sendto;
ng_pktsnip_t *pkt, *netif_hdr;
pkt = ng_pktbuf_add(NULL, NULL, bytes, NG_NETTYPE_UNDEF);
if (pkt == NULL) {
DEBUG("slip: no space left in packet buffer\n");
return;
}
netif_hdr = ng_pktbuf_add(pkt, NULL, sizeof(ng_netif_hdr_t),
NG_NETTYPE_NETIF);
if (netif_hdr == NULL) {
DEBUG("slip: no space left in packet buffer\n");
ng_pktbuf_release(pkt);
return;
}
hdr = netif_hdr->data;
ng_netif_hdr_init(hdr, 0, 0);
hdr->if_pid = thread_getpid();
if (ringbuffer_get(dev->in_buf, pkt->data, bytes) != bytes) {
DEBUG("slip: could not read %zu bytes from ringbuffer\n", bytes);
ng_pktbuf_release(pkt);
return;
}
#ifdef MODULE_NG_IPV6
if ((pkt->size >= sizeof(ng_ipv6_hdr_t)) && ng_ipv6_hdr_is_ipv6_hdr(pkt->data)) {
pkt->type = NG_NETTYPE_IPV6;
}
#endif
sendto = ng_netreg_lookup(pkt->type, NG_NETREG_DEMUX_CTX_ALL);
if (sendto == NULL) {
DEBUG("slip: unable to forward packet of type %i\n", pkt->type);
ng_pktbuf_release(pkt);
}
ng_pktbuf_hold(pkt, ng_netreg_num(pkt->type, NG_NETREG_DEMUX_CTX_ALL) - 1);
while (sendto != NULL) {
DEBUG("slip: sending pkt %p to PID %u\n", pkt, sendto->pid);
ng_netapi_receive(sendto->pid, pkt);
sendto = ng_netreg_getnext(sendto);
}
}
static inline void _slip_send_char(ng_slip_dev_t *dev, char c)
{
ringbuffer_add_one(dev->out_buf, c);
uart_tx_begin(dev->uart);
}
/* SLIP send handler */
static void _slip_send(ng_slip_dev_t *dev, ng_pktsnip_t *pkt)
{
ng_pktsnip_t *ptr;
ptr = pkt->next; /* ignore ng_netif_hdr_t, we don't need it */
while (ptr != NULL) {
DEBUG("slip: send pktsnip of length %zu over UART_%d\n", ptr->size, 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);
ng_pktbuf_release(pkt);
}
static void *_slip(void *args)
{
ng_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();
ng_netif_add(dev->slip_pid);
DEBUG("slip: SLIP runs on UART_%d\n", uart);
while (1) {
DEBUG("slip: waiting for incoming messages\n");
msg_receive(&msg);
switch (msg.type) {
case _SLIP_MSG_TYPE:
DEBUG("slip: incoming message from UART in buffer\n");
_slip_receive(dev, (size_t)msg.content.value);
break;
case NG_NETAPI_MSG_TYPE_SND:
DEBUG("slip: NG_NETAPI_MSG_TYPE_SND received\n");
_slip_send(dev, (ng_pktsnip_t *)msg.content.ptr);
break;
case NG_NETAPI_MSG_TYPE_GET:
case NG_NETAPI_MSG_TYPE_SET:
DEBUG("slip: NG_NETAPI_MSG_TYPE_GET or NG_NETAPI_MSG_TYPE_SET received\n");
reply.type = NG_NETAPI_MSG_TYPE_ACK;
reply.content.value = (uint32_t)(-ENOTSUP);
DEBUG("slip: I don't support these but have to reply.\n");
msg_reply(&msg, &reply);
break;
}
}
/* should be never reached */
return NULL;
}
kernel_pid_t ng_slip_init(ng_slip_dev_t *dev, uart_t uart, uint32_t baudrate,
char *stack, size_t stack_size, char priority)
{
int res;
kernel_pid_t pid;
/* reset device descriptor fields */
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));
ringbuffer_init(dev->out_buf, dev->tx_mem, sizeof(dev->tx_mem));
/* initialize UART */
DEBUG("slip: initialize UART_%d\n", uart);
res = uart_init(uart, baudrate, _slip_rx_cb, _slip_tx_cb, dev);
if (res < 0) {
DEBUG("slip: error initializing UART_%i with baudrate %u\n",
uart, baudrate);
return -ENODEV;
}
/* start SLIP thread */
DEBUG("slip: starting SLIP thread\n");
pid = thread_create(stack, stack_size, priority, CREATE_STACKTEST,
_slip, dev, _SLIP_NAME);
if (pid < 0) {
DEBUG("slip: unable to create SLIP thread\n");
return -EFAULT;
}
return res;
}