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) */
|
||||
|
||||
#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)
|
||||
{
|
||||
|
|
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__ */
|
|
@ -5,3 +5,4 @@ zephyr_sources(
|
|||
)
|
||||
|
||||
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
|
||||
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
|
||||
|
|
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