Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gnrc_sock_tcp: add gnrc sock tcp #16494

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions sys/include/net/gnrc/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@
#include "net/gnrc/pkt.h"
#include "net/gnrc/tcp/tcb.h"

#ifdef SOCK_HAS_IPV6
#include "net/sock.h"
#else
#ifdef MODULE_GNRC_IPV6
#include "net/gnrc/ipv6.h"
#endif
#endif

#ifdef __cplusplus
extern "C" {
Expand All @@ -44,6 +48,11 @@ extern "C" {
#define GNRC_TCP_NO_TIMEOUT (UINT32_MAX)
#endif

#ifdef SOCK_HAS_IPV6
/* Re-use sock endpoint if sock is available and supporting IPv6. */
typedef struct _sock_tl_ep gnrc_tcp_ep_t;

#else
/**
* @brief Address information for a single TCP connection endpoint.
* @extends sock_tcp_ep_t
Expand All @@ -59,6 +68,7 @@ typedef struct {
uint16_t netif; /**< Network interface ID */
uint16_t port; /**< Port number (in host byte order) */
} gnrc_tcp_ep_t;
#endif

/**
* @brief Initialize TCP connection endpoint.
Expand Down
6 changes: 3 additions & 3 deletions sys/include/net/gnrc/tcp/tcb.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ extern "C" {
/**
* @brief Transmission control block of GNRC TCP.
*/
typedef struct _transmission_control_block {
typedef struct sock_tcp {
uint8_t address_family; /**< Address Family of local_addr / peer_addr */
#ifdef MODULE_GNRC_IPV6
uint8_t local_addr[sizeof(ipv6_addr_t)]; /**< Local IP address */
Expand Down Expand Up @@ -76,13 +76,13 @@ typedef struct _transmission_control_block {
ringbuffer_t rcv_buf; /**< Receive buffer data structure */
mutex_t fsm_lock; /**< Mutex for FSM access synchronization */
mutex_t function_lock; /**< Mutex for function call synchronization */
struct _transmission_control_block *next; /**< Pointer next TCB */
struct sock_tcp *next; /**< Pointer next TCB */
} gnrc_tcp_tcb_t;

/**
* @brief Transmission control block queue.
*/
typedef struct _transmission_control_block_queue {
typedef struct sock_tcp_queue {
mutex_t lock; /**< Mutex for access synchronization */
gnrc_tcp_tcb_t *tcbs; /**< Pointer to TCB sequence */
size_t tcbs_len; /**< Number of TCBs behind member tcbs */
Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ endif
ifneq (,$(filter gnrc_sock_udp,$(USEMODULE)))
DIRS += sock/udp
endif
ifneq (,$(filter gnrc_sock_tcp,$(USEMODULE)))
DIRS += sock/tcp
endif
ifneq (,$(filter gnrc_udp,$(USEMODULE)))
DIRS += transport_layer/udp
endif
Expand Down
7 changes: 7 additions & 0 deletions sys/net/gnrc/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ ifneq (,$(filter gnrc_sock_udp,$(USEMODULE)))
USEMODULE += random # to generate random ports
endif

ifneq (,$(filter gnrc_sock_tcp,$(USEMODULE)))
USEMODULE += gnrc_tcp
endif

ifneq (,$(filter gnrc_sock,$(USEMODULE)))
USEMODULE += gnrc_netapi_mbox
USEMODULE += sock
Expand Down Expand Up @@ -398,6 +402,9 @@ ifneq (,$(filter gnrc,$(USEMODULE)))
ifneq (,$(filter sock_udp, $(USEMODULE)))
USEMODULE += gnrc_sock_udp
endif
ifneq (,$(filter sock_tcp, $(USEMODULE)))
USEMODULE += gnrc_sock_tcp
endif
endif

ifneq (,$(filter gnrc_pktbuf, $(USEMODULE)))
Expand Down
2 changes: 2 additions & 0 deletions sys/net/gnrc/sock/include/sock_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@
#include "mbox.h"
#include "net/af.h"
#include "net/gnrc.h"
#include "net/gnrc/tcp.h"
#include "net/gnrc/netreg.h"
#ifdef SOCK_HAS_ASYNC
#include "net/sock/async/types.h"
#endif
#include "net/sock/ip.h"
#include "net/sock/udp.h"
#include "net/sock/tcp.h"

#ifdef __cplusplus
extern "C" {
Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/sock/tcp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
MODULE = gnrc_sock_tcp

include $(RIOTBASE)/Makefile.base
146 changes: 146 additions & 0 deletions sys/net/gnrc/sock/tcp/gnrc_sock_tcp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Copyright (C) 2021 Simon Brummer <[email protected]>
*
* 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
* @brief GNRC implementation of @ref net_sock_tcp
*
* @author Simon Brummer <[email protected]>
*/

#include <assert.h>

#include "net/gnrc/tcp.h"
#include "net/sock/tcp.h"
#include "sock_types.h"

int sock_tcp_connect(sock_tcp_t *sock, const sock_tcp_ep_t *remote,
uint16_t local_port, uint16_t flags)
{
/* Asserts defined by API. */
assert(sock != NULL);
assert(remote != NULL);
assert(remote->port != 0);

/* Asserts to protect GNRC_TCP. Flags are not supported. */
assert(flags == 0);
(void) flags;

/* Initialize given TCB and try to open a connection */
gnrc_tcp_tcb_init(sock);

/* Forward call to gnrc_tcp_open. Return codes are identical except those that are
* not generated by gnrc_tcp_open: -ENETUNREACH and -EPERM */
return gnrc_tcp_open(sock, remote, local_port);
}

int sock_tcp_listen(sock_tcp_queue_t *queue, const sock_tcp_ep_t *local,
sock_tcp_t *queue_array, unsigned queue_len, uint16_t flags)
{
/* Asserts defined by API. */
assert(queue != NULL);
assert(local != NULL);
assert(local->port != 0);
assert(queue_array != NULL);
assert(queue_len != 0);

/* Asserts to protect GNRC_TCP. Flags are not supported. */
assert(flags == 0);
(void) flags;

/* Initialize given TCB queue, all given tcbs and forward call */
gnrc_tcp_tcb_queue_init(queue);
for (unsigned i = 0; i < queue_len; ++i) {
gnrc_tcp_tcb_init(&queue_array[i]);
}
return gnrc_tcp_listen(queue, queue_array, queue_len, local);
}

void sock_tcp_disconnect(sock_tcp_t *sock)
{
/* Asserts defined by API. */
assert(sock != NULL);
gnrc_tcp_close(sock);
}

void sock_tcp_stop_listen(sock_tcp_queue_t *queue)
{
/* Asserts defined by API. */
assert(queue != NULL);
gnrc_tcp_stop_listen(queue);
}

int sock_tcp_get_local(sock_tcp_t *sock, sock_tcp_ep_t *ep)
{
/* Asserts defined by API. */
assert(sock != NULL);
assert(ep != NULL);
return gnrc_tcp_get_local(sock, ep);
}

int sock_tcp_get_remote(sock_tcp_t *sock, sock_tcp_ep_t *ep)
{
/* Asserts defined by API. */
assert(sock != NULL);
assert(ep != NULL);
return gnrc_tcp_get_remote(sock, ep);
}

int sock_tcp_queue_get_local(sock_tcp_queue_t *queue, sock_tcp_ep_t *ep)
{
/* Asserts defined by API. */
assert(queue != NULL);
assert(ep != NULL);
return gnrc_tcp_queue_get_local(queue, ep);
}

int sock_tcp_accept(sock_tcp_queue_t *queue, sock_tcp_t **sock, uint32_t timeout)
{
/* Asserts defined by API. */
assert(queue != NULL);
assert(sock != NULL);

/* Map SOCK_NO_TIMEOUT to GNRC_TCP_NO_TIMEOUT */
if (timeout == SOCK_NO_TIMEOUT) {
timeout = GNRC_TCP_NO_TIMEOUT;
}

/* Forward call to gnrc_tcp_accept.
* NOTE: Errorcodes -ECONNABORTED, -EPERM are not returned by
* gnrc_tcp_accept. All other error codes share the same semantics. */
return gnrc_tcp_accept(queue, sock, timeout);
}

ssize_t sock_tcp_read(sock_tcp_t *sock, void *data, size_t max_len, uint32_t timeout)
{
/* Asserts defined by API. */
assert(sock != NULL);
assert(data != NULL);

/* Map SOCK_NO_TIMEOUT to GNRC_TCP_NO_TIMEOUT */
if (timeout == SOCK_NO_TIMEOUT) {
timeout = GNRC_TCP_NO_TIMEOUT;
}

/* Forward call to gnrc_tcp_recv: All error codes share the same semantics */
return gnrc_tcp_recv(sock, data, max_len, timeout);
}

ssize_t sock_tcp_write(sock_tcp_t *sock, const void *data, size_t len)
{
/* Asserts defined by API. */
assert(sock != NULL);
assert(data != NULL);

/* Forward call to gnrc_tcp_send.
* NOTE: gnrc_tcp_send offers a timeout. By setting it to 0, the call blocks
* until at least some data was transmitted. */
return gnrc_tcp_send(sock, data, len, 0);
}
59 changes: 59 additions & 0 deletions tests/gnrc_sock_tcp/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
include ../Makefile.tests_common

# Basic Configuration
BOARD ?= native
TAP ?= tap0

# Shorten default TCP timeouts to speedup testing
MSL_MS ?= 1000
TIMEOUT_MS ?= 3000

# This test depends on tap device setup (only allowed by root)
# Suppress test execution to avoid CI errors
TEST_ON_CI_BLACKLIST += all

ifeq (native,$(BOARD))
TERMFLAGS ?= $(TAP)
else
ETHOS_BAUDRATE ?= 115200
CFLAGS += -DETHOS_BAUDRATE=$(ETHOS_BAUDRATE)
TERMDEPS += ethos
TERMPROG ?= sudo $(RIOTTOOLS)/ethos/ethos
TERMFLAGS ?= $(TAP) $(PORT) $(ETHOS_BAUDRATE)
endif

USEMODULE += auto_init_gnrc_netif
USEMODULE += gnrc_ipv6_default
USEMODULE += gnrc_sock_tcp
USEMODULE += gnrc_pktbuf_cmd
USEMODULE += gnrc_netif_single # Only one interface used and it makes
# shell commands easier
USEMODULE += shell
USEMODULE += shell_commands
USEMODULE += od

# Export used tap device to environment
export TAPDEV = $(TAP)

.PHONY: ethos

ethos:
$(Q)env -u CC -u CFLAGS $(MAKE) -C $(RIOTTOOLS)/ethos

include $(RIOTBASE)/Makefile.include

# Set CONFIG_GNRC_TCP_MSL via CFLAGS if not being set via Kconfig
ifndef CONFIG_GNRC_TCP_MSL_MS
CFLAGS += -DCONFIG_GNRC_TCP_MSL_MS=$(MSL_MS)
endif

# Set CONFIG_GNRC_TCP_CONNECTION_TIMEOUT_DURATION via CFLAGS if not being set
# via Kconfig
ifndef CONFIG_GNRC_TCP_CONNECTION_TIMEOUT_DURATION_MS
CFLAGS += -DCONFIG_GNRC_TCP_CONNECTION_TIMEOUT_DURATION_MS=$(TIMEOUT_MS)
endif

# Set the shell echo configuration via CFLAGS if not being controlled via Kconfig
ifndef CONFIG_KCONFIG_USEMODULE_SHELL
CFLAGS += -DCONFIG_SHELL_NO_ECHO
endif
6 changes: 6 additions & 0 deletions tests/gnrc_sock_tcp/Makefile.board.dep
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Put board specific dependencies here
ifeq (native,$(BOARD))
USEMODULE += netdev_tap
else
USEMODULE += stdio_ethos
endif
44 changes: 44 additions & 0 deletions tests/gnrc_sock_tcp/Makefile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-leonardo \
arduino-mega2560 \
arduino-nano \
arduino-uno \
atmega1284p \
atmega328p \
atmega328p-xplained-mini \
atxmega-a1u-xpro \
atxmega-a3bu-xplained \
bluepill-stm32f030c8 \
derfmega128 \
hifive1 \
hifive1b \
i-nucleo-lrwan1 \
im880b \
mega-xplained \
microduino-corerf \
msb-430 \
msb-430h \
nucleo-f030r8 \
nucleo-f031k6 \
nucleo-f042k6 \
nucleo-f070rb \
nucleo-f072rb \
nucleo-f303k8 \
nucleo-f334r8 \
nucleo-l011k4 \
nucleo-l031k6 \
nucleo-l053r8 \
samd10-xmini \
saml10-xpro \
saml11-xpro \
slstk3400a \
stk3200 \
stm32f030f4-demo \
stm32f0discovery \
stm32l0538-disco \
telosb \
waspmote-pro \
z1 \
zigduino \
#
20 changes: 20 additions & 0 deletions tests/gnrc_sock_tcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Test description
==========
The testsuite tests the GNRC TCP integration into the SOCK TCP interface.
The tests offer only basic verification of the SOCK TCP interface since GNRC TCP aims
follow the SOCK TCP interface as close as possible, detailed tests are under tests/gnrc_tcp

Setup
==========
The test requires a tap-device setup. This can be achieved by running 'dist/tools/tapsetup/tapsetup'
or by executing the following commands:

sudo ip tuntap add tap0 mode tap user ${USER}
sudo ip link set tap0 up

Usage
==========
make BOARD=<BOARD_NAME> all flash
sudo make BOARD=<BOARD_NAME> test-as-root

'sudo' is required due to ethos and raw socket usage.
Loading