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:
parent
213a88f7ff
commit
c21b0fb357
6 changed files with 249 additions and 8 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
147
include/net/socket_offload.h
Normal file
147
include/net/socket_offload.h
Normal 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__ */
|
56
include/net/socket_offload_ops.h
Normal file
56
include/net/socket_offload_ops.h
Normal 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__ */
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
18
subsys/net/lib/sockets/socket_offload.c
Normal file
18
subsys/net/lib/sockets/socket_offload.c
Normal 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;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue