doc: net: sockets: Add offloading and dispatcher documentation
Add brief documentation for socket offloading and socket dispatcher. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
6da10468ad
commit
536e061181
1 changed files with 131 additions and 0 deletions
|
@ -143,6 +143,137 @@ Secure sockets offer the following options for socket management:
|
||||||
|
|
||||||
.. doxygengroup:: secure_sockets_options
|
.. doxygengroup:: secure_sockets_options
|
||||||
|
|
||||||
|
Socket offloading
|
||||||
|
*****************
|
||||||
|
|
||||||
|
Zephyr allows to register custom socket implementations (called offloaded
|
||||||
|
sockets). This allows for seamless integration for devices which provide an
|
||||||
|
external IP stack and expose socket-like API.
|
||||||
|
|
||||||
|
Socket offloading can be enabled with :kconfig:option:`CONFIG_NET_SOCKETS_OFFLOAD`
|
||||||
|
option. A network driver that wants to register a new socket implementation
|
||||||
|
should use :c:macro:`NET_SOCKET_OFFLOAD_REGISTER` macro. The macro accepts the
|
||||||
|
following parameters:
|
||||||
|
|
||||||
|
* socket_name - an arbitrary name for the socket implementation.
|
||||||
|
* prio - socket implementation priority, the higher priority is, the earlier
|
||||||
|
particular implementation is processed when creating a new socket.
|
||||||
|
Lower numeric value indicate higher priority.
|
||||||
|
* _family - socket family implemented by the offloaded socket. ``AF_UNSPEC``
|
||||||
|
indicate any family.
|
||||||
|
* _is_supported - a filtering function, used to verify whether particular
|
||||||
|
socket family, type and protocol are supported by the
|
||||||
|
offloaded socket implementation.
|
||||||
|
* _handler - a function compatible with :c:func:`socket` API, used to create
|
||||||
|
an offloaded socket.
|
||||||
|
|
||||||
|
Every offloaded socket implementation should also implement a set of socket
|
||||||
|
APIs, specified in :c:struct:`socket_op_vtable` struct.
|
||||||
|
|
||||||
|
The function registered for socket creation should allocate a new file
|
||||||
|
descriptor using :c:func:`z_reserve_fd` function. Any additional actions,
|
||||||
|
specific to the creation of a particular offloaded socket implementation should
|
||||||
|
take place after the file descriptor is allocated. As a final step, if the
|
||||||
|
offloaded socket was created successfully, the file descriptor should be
|
||||||
|
finalized with :c:func:`z_finalize_fd` function. The finalize function allows
|
||||||
|
to register a :c:struct:`socket_op_vtable` structure implementing socket APIs
|
||||||
|
for an offloaded socket along with an optional socket context data pointer.
|
||||||
|
|
||||||
|
Finally, when an offloaded network interface is initialized, it should indicate
|
||||||
|
that the interface is offloaded with :c:func:`net_if_socket_offload_set`
|
||||||
|
function. The function registers the function used to create an offloaded socket
|
||||||
|
(the same as the one provided in :c:macro:`NET_SOCKET_OFFLOAD_REGISTER`) at the
|
||||||
|
network interface.
|
||||||
|
|
||||||
|
Offloaded socket creation
|
||||||
|
=========================
|
||||||
|
|
||||||
|
When application creates a new socket with :c:func:`socket` function, the
|
||||||
|
network stack iterates over all registered socket implementations (native and
|
||||||
|
offloaded). Higher priority socket implementations are processed first.
|
||||||
|
For each registered socket implementation, an address family is verified, and if
|
||||||
|
it matches (or the socket was registered as ``AF_UNSPEC``), the corresponding
|
||||||
|
``_is_supported`` function is called to verify the remaining socket parameters.
|
||||||
|
The first implementation that fulfills the socket requirements (i. e.
|
||||||
|
``_is_supported`` returns true) will create a new socket with its ``_handler``
|
||||||
|
function.
|
||||||
|
|
||||||
|
The above indicates the importance of the socket priority. If multiple socket
|
||||||
|
implementations support the same set of socket family/type/protocol, the first
|
||||||
|
implementation processed by the system will create a socket. Therefore it's
|
||||||
|
important to give the highest priority to the implementation that should be the
|
||||||
|
system default.
|
||||||
|
|
||||||
|
The socket priority for native socket implementation is configured with Kconfig.
|
||||||
|
Use :kconfig:option:`CONFIG_NET_SOCKETS_TLS_PRIORITY` to set the priority for
|
||||||
|
the native TLS sockets.
|
||||||
|
Use :kconfig:option:`CONFIG_NET_SOCKETS_PRIORITY_DEFAULT` to set the priority
|
||||||
|
for the remaining native sockets.
|
||||||
|
|
||||||
|
Dealing with multiple offloaded interfaces
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
As the :c:func:`socket` function does not allow to specify which network
|
||||||
|
interface should be used by a socket, it's not possible to choose a specific
|
||||||
|
implementation in case multiple offloaded socket implementations, supporting the
|
||||||
|
same type of sockets, are available. The same problem arises when both native
|
||||||
|
and offloaded sockets are available in the system.
|
||||||
|
|
||||||
|
To address this problem, a special socket implementation (called socket
|
||||||
|
dispatcher) was introduced. The sole reason for this module is to postpone the
|
||||||
|
socket creation for until the first operation on a socket is performed. This
|
||||||
|
leaves an opening to use ``SO_BINDTODEVICE`` socket option, to bind a socket to
|
||||||
|
a particular network interface (and thus offloaded socket implementation).
|
||||||
|
The socket dispatcher can be enabled with :kconfig:option:`CONFIG_NET_SOCKETS_OFFLOAD_DISPATCHER`
|
||||||
|
Kconfig option.
|
||||||
|
|
||||||
|
When enabled, the application can specify the network interface to use with
|
||||||
|
:c:func:`setsockopt` function:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
/* A "dispatcher" socket is created */
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
|
||||||
|
struct ifreq ifreq = {
|
||||||
|
.ifr_name = "SimpleLink"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The socket is "dispatched" to a particular network interface
|
||||||
|
* (offloaded or not).
|
||||||
|
*/
|
||||||
|
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq));
|
||||||
|
|
||||||
|
Similarly, if TLS is supported by both native and offloaded sockets,
|
||||||
|
``TLS_NATIVE`` socket option can be used to indicate that a native TLS socket
|
||||||
|
should be created. The underlying socket can then be bound to a particular
|
||||||
|
network interface:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
/* A "dispatcher" socket is created */
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TLS_1_2);
|
||||||
|
|
||||||
|
int tls_native = 1;
|
||||||
|
|
||||||
|
/* The socket is "dispatched" to a native TLS socket implmeentation.
|
||||||
|
* The underlying socket is a "dispatcher" socket now.
|
||||||
|
*/
|
||||||
|
setsockopt(sock, SOL_TLS, TLS_NATIVE, &tls_native, sizeof(tls_native));
|
||||||
|
|
||||||
|
struct ifreq ifreq = {
|
||||||
|
.ifr_name = "SimpleLink"
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The underlying socket is "dispatched" to a particular network interface
|
||||||
|
* (offloaded or not).
|
||||||
|
*/
|
||||||
|
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifreq, sizeof(ifreq));
|
||||||
|
|
||||||
|
In case no ``SO_BINDTODEVICE`` socket option is used on a socket, the socket
|
||||||
|
will be dispatched according to the default priority and filtering rules on a
|
||||||
|
first socket API call.
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
*************
|
*************
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue