net: sockets: Add a socket offload module

This patch enables BSD socket offload to a dedicated
TCP/IP offload engine.

This provides a simpler, more direct mechanism than going
through NET_OFFLOAD (zsock -> net_context -> socket conversions)
for those devices which provide complete TCP/IP offload at the
BSD socket level, and whose use cases do not require
IP routing between multiple network interfaces.

To use, configure CONFIG_NET_SOCKETS_OFFLOAD=y, and register
socket_offload_ops with this module.

Fixes #3706

Signed-off-by: Gil Pitney <gil.pitney@linaro.org>
This commit is contained in:
Gil Pitney 2017-07-18 13:54:53 -07:00 committed by Jukka Rissanen
commit c21b0fb357
6 changed files with 249 additions and 8 deletions

View file

@ -186,6 +186,8 @@ int ztls_setsockopt(int sock, int level, int optname,
#endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */
#if defined(CONFIG_NET_SOCKETS_POSIX_NAMES) #if defined(CONFIG_NET_SOCKETS_POSIX_NAMES)
#define pollfd zsock_pollfd
#if !defined(CONFIG_NET_SOCKETS_OFFLOAD)
static inline int socket(int family, int type, int proto) static inline int socket(int family, int type, int proto)
{ {
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
@ -296,13 +298,6 @@ static inline int poll(struct zsock_pollfd *fds, int nfds, int timeout)
#endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */
} }
#define pollfd zsock_pollfd
#define POLLIN ZSOCK_POLLIN
#define POLLOUT ZSOCK_POLLOUT
#define MSG_PEEK ZSOCK_MSG_PEEK
#define MSG_DONTWAIT ZSOCK_MSG_DONTWAIT
static inline int getsockopt(int sock, int level, int optname, static inline int getsockopt(int sock, int level, int optname,
void *optval, socklen_t *optlen) void *optval, socklen_t *optlen)
{ {
@ -323,6 +318,16 @@ static inline int setsockopt(int sock, int level, int optname,
#endif #endif
} }
#else
#include <net/socket_offload.h>
#endif /* !defined(CONFIG_NET_SOCKETS_OFFLOAD) */
#define POLLIN ZSOCK_POLLIN
#define POLLOUT ZSOCK_POLLOUT
#define MSG_PEEK ZSOCK_MSG_PEEK
#define MSG_DONTWAIT ZSOCK_MSG_DONTWAIT
static inline char *inet_ntop(sa_family_t family, const void *src, char *dst, static inline char *inet_ntop(sa_family_t family, const void *src, char *dst,
size_t size) size_t size)
{ {

View file

@ -0,0 +1,147 @@
/*
* Copyright (c) 2018 Linaro Limited.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Socket Offload Redirect API
*/
#ifndef __SOCKET_OFFLOAD_H__
#define __SOCKET_OFFLOAD_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <net/socket_offload_ops.h>
extern const struct socket_offload *socket_ops;
static inline int socket(int family, int type, int proto)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->socket);
return socket_ops->socket(family, type, proto);
}
static inline int close(int sock)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->close);
return socket_ops->close(sock);
}
static inline int accept(int sock, struct sockaddr *addr,
socklen_t *addrlen)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->accept);
return socket_ops->accept(sock, addr, addrlen);
}
static inline int bind(int sock, const struct sockaddr *addr,
socklen_t addrlen)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->bind);
return socket_ops->bind(sock, addr, addrlen);
}
static inline int listen(int sock, int backlog)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->listen);
return socket_ops->listen(sock, backlog);
}
static inline int connect(int sock, const struct sockaddr *addr,
socklen_t addrlen)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->connect);
return socket_ops->connect(sock, addr, addrlen);
}
static inline int poll(struct pollfd *fds, int nfds, int timeout)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->poll);
return socket_ops->poll(fds, nfds, timeout);
}
static inline int setsockopt(int sock, int level, int optname,
const void *optval,
socklen_t optlen)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->setsockopt);
return socket_ops->setsockopt(sock, level, optname, optval, optlen);
}
static inline int getsockopt(int sock, int level, int optname,
void *optval, socklen_t *optlen)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->getsockopt);
return socket_ops->getsockopt(sock, level, optname, optval, optlen);
}
static inline ssize_t recv(int sock, void *buf, size_t max_len,
int flags)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->recv);
return socket_ops->recv(sock, buf, max_len, flags);
}
static inline ssize_t recvfrom(int sock, void *buf,
short int len,
short int flags,
struct sockaddr *from,
socklen_t *fromlen)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->recvfrom);
return socket_ops->recvfrom(sock, buf, len, flags, from, fromlen);
}
static inline ssize_t send(int sock, const void *buf, size_t len,
int flags)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->send);
return socket_ops->send(sock, buf, len, flags);
}
static inline ssize_t sendto(int sock, const void *buf,
size_t len, int flags,
const struct sockaddr *to,
socklen_t tolen)
{
__ASSERT_NO_MSG(socket_ops);
__ASSERT_NO_MSG(socket_ops->sendto);
return socket_ops->sendto(sock, buf, len, flags, to, tolen);
}
#ifdef __cplusplus
}
#endif
#endif /* __SOCKET_OFFLOAD_H__ */

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2018 Linaro Limited.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief Socket Offload Redirect API
*/
#ifndef __SOCKET_OFFLOAD_OPS_H__
#define __SOCKET_OFFLOAD_OPS_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <net/net_ip.h>
#include <net/socket.h> /* needed for struct pollfd */
/*
* It is assumed that these offload functions follow the
* POSIX socket API standard for arguments, return values and setting of errno.
*/
struct socket_offload {
/* POSIX Socket Functions: */
int (*socket)(int family, int type, int proto);
int (*close)(int sock);
int (*accept)(int sock, struct sockaddr *addr, socklen_t *addrlen);
int (*bind)(int sock, const struct sockaddr *addr, socklen_t addrlen);
int (*listen)(int sock, int backlog);
int (*connect)(int sock, const struct sockaddr *addr,
socklen_t addrlen);
int (*poll)(struct pollfd *fds, int nfds, int timeout);
int (*setsockopt)(int sock, int level, int optname,
const void *optval, socklen_t optlen);
int (*getsockopt)(int sock, int level, int optname, void *optval,
socklen_t *optlen);
ssize_t (*recv)(int sock, void *buf, size_t max_len, int flags);
ssize_t (*recvfrom)(int sock, void *buf, short int len,
short int flags, struct sockaddr *from,
socklen_t *fromlen);
ssize_t (*send)(int sock, const void *buf, size_t len, int flags);
ssize_t (*sendto)(int sock, const void *buf, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen);
};
extern void socket_offload_register(const struct socket_offload *ops);
#ifdef __cplusplus
}
#endif
#endif /* __SOCKET_OFFLOAD_OPS_H__ */

View file

@ -4,4 +4,5 @@ zephyr_sources(
sockets.c sockets.c
) )
zephyr_sources_ifdef(CONFIG_NET_SOCKETS_SOCKOPT_TLS sockets_tls.c) zephyr_sources_ifdef(CONFIG_NET_SOCKETS_SOCKOPT_TLS sockets_tls.c)
zephyr_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD socket_offload.c)

View file

@ -82,6 +82,20 @@ config NET_SOCKETS_TLS_MAX_CIPHERSUITES
By default, all ciphersuites that are available in the system are By default, all ciphersuites that are available in the system are
available to the socket. available to the socket.
config NET_SOCKETS_OFFLOAD
bool "Offload Socket APIs [EXPERIMENTAL]"
select NET_SOCKETS_POSIX_NAMES
help
Enables direct offloading of socket operations to dedicated TCP/IP
hardware.
This feature is intended to save resources by bypassing the Zephyr
TCP/IP stack in the case where there is only one network interface
required in the system, providing full BSD socket offload capability.
As a result, it bypasses any potential IP routing that Zephyr might
provide between multiple network interfaces.
See NET_OFFLOAD for a more deeply integrated approach which offloads
from the net_context() API within the Zephyr IP stack.
config NET_DEBUG_SOCKETS config NET_DEBUG_SOCKETS
bool "Debug BSD Sockets compatible API calls" bool "Debug BSD Sockets compatible API calls"
default y if NET_LOG_GLOBAL default y if NET_LOG_GLOBAL

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2018 Linaro Limited.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <net/socket_offload.h>
/* Only one provider may register socket operations upon boot. */
const struct socket_offload *socket_ops;
void socket_offload_register(const struct socket_offload *ops)
{
__ASSERT_NO_MSG(ops);
__ASSERT_NO_MSG(socket_ops == NULL);
socket_ops = ops;
}