diff --git a/include/net/socket.h b/include/net/socket.h index 47de801405c9a6..105f2ee5c8b3e4 100644 --- a/include/net/socket.h +++ b/include/net/socket.h @@ -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 +#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) { diff --git a/include/net/socket_offload.h b/include/net/socket_offload.h new file mode 100644 index 00000000000000..8ef97e8bcb9fa0 --- /dev/null +++ b/include/net/socket_offload.h @@ -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 + +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__ */ diff --git a/include/net/socket_offload_ops.h b/include/net/socket_offload_ops.h new file mode 100644 index 00000000000000..0fbc5a66a52022 --- /dev/null +++ b/include/net/socket_offload_ops.h @@ -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 +#include +#include /* 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__ */ diff --git a/subsys/net/lib/sockets/CMakeLists.txt b/subsys/net/lib/sockets/CMakeLists.txt index a2f1b942d9eaba..0136e5a7ba82a5 100644 --- a/subsys/net/lib/sockets/CMakeLists.txt +++ b/subsys/net/lib/sockets/CMakeLists.txt @@ -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) diff --git a/subsys/net/lib/sockets/Kconfig b/subsys/net/lib/sockets/Kconfig index 5abad217b27be1..339fc5dd1aee25 100644 --- a/subsys/net/lib/sockets/Kconfig +++ b/subsys/net/lib/sockets/Kconfig @@ -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 diff --git a/subsys/net/lib/sockets/socket_offload.c b/subsys/net/lib/sockets/socket_offload.c new file mode 100644 index 00000000000000..1fbeb1f64748b0 --- /dev/null +++ b/subsys/net/lib/sockets/socket_offload.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018 Linaro Limited. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* 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; +}