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) */
#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)
{
#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) */
}
#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,
void *optval, socklen_t *optlen)
{
@ -323,6 +318,16 @@ static inline int setsockopt(int sock, int level, int optname,
#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,
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
)
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
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
bool "Debug BSD Sockets compatible API calls"
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;
}