Dovetail provides a way for a companion core to implement protocols in
the new out-of-band protocol family (PF_OOB
), or extend existing
protocol implementations with out-of-band I/O capabilities (for
instance, the EVL network stack extends PF_INET/udp
and
PF_PACKET
).
To provide a service access point to the network stack a companion
core may implement, Dovetail builds on the regular socket abstraction
available from the in-band kernel, extending its capabilities to
enabling out-of-band I/O. In other words, there is no
Dovetail-specific socket implementation, only a small set of features
added to the regular socket implementation in order for a companion
core to implement a protocol or even extend a pre-existing one. This
set is enabled when the SOCK_OOB
flag is given at socket creation by
the application code. For instance, the following snippet can be used
with the EVL network stack which implements the PACKET protocol family
on raw sockets:
/*
* Get a raw socket with out-of-band capabilities.
*/
int s = socket(AF_PACKET, SOCK_RAW | SOCK_OOB, 0);
A pointer to an out-of-band context descriptor is added to the INET
socket data structure (i.e. struct sock
). When non-NULL, the socket
has an out-of-band context managed by a companion core which should
populate it on attachment request
from the in-band network stack. The core defines the actual C type of
this structure.
Echoing the logic in place for managing files from the out-of-band execution stage, Dovetail provides the necessary support exclusively for handling I/O requests from that stage, i.e. receiving and sending data. Creating a socket, closing it, plus all ancillary operations such as binding, connecting, shutting down connections and so on are left to the regular in-band network stack as usual (In other words, don’t expect Dovetail to provide support for e.g. creating a socket from the out-of-band stage or implementing a real-time capable binding operation, it won’t).
In order for a companion core to manage sockets with out-of-band I/O capabilities, Dovetail adds several hooks to the kernel.
When a socket is created with the SOCK_OOB
flag, Dovetail allows the
companion core to set up its own context data by calling this
routine. The descriptor received is already fully constructed on the
in-band side at the time of the call. sock_oob_attach() should be the place where the oob_data
pointer visible in struct sock
is populated.
The address of the BSD socket descriptor to attach to the companion core.
sock_oob_attach() should return zero on success, or a negative errno code.
A call to sock_oob_release()
happens when sock
- for which a previous call to
sock_oob_attach() has succeeded -
is closed on the in-band side. This hook is the place where the
companion core may want to synchronize with the ongoing out-of-band
activity on the socket, waiting for it to finish before returning.
When this routine is called, the BSD sock
is still bound to a file,
but its representation in the network layer sock->sk
might already
be stale. Any deallocation of resources referred to by
sock->oob_data
should be postponed to sock_oob_destroy().
The address of the BSD socket descriptor to detach from the companion core.
A call to sock_oob_destroy()
happens when the last reference to the INET socket sk
is dropped,
which may happen long after sock_oob_release() is called for the associated BSD socket
descriptor. This routine should deallocate the resources obtained by
sock_oob_attach() for tracking
this socket on the out-of-band side.
The address of the INET socket descriptor in the processed of being destroyed.
This hook is called when the code implementing an in-band protocol
family (i.e. distinct from PF_OOB
) attempts to bind a
socket bearing the
SOCK_OOB
flag to an address, allowing the companion core to extend
the binding logic as it sees fit. At the moment, this call is issued
by the PF_INET
and PF_PACKET
domains
exclusively. sock_oob_bind() runs
once the regular binding operation for the domain has succeeded.
The address of the INET socket descriptor to bind an address to.
This call return zero on success, otherwise a negative errno status. On error, the whole binding operation fails, including the in-band binding.
This hook is called when the code implementing an in-band protocol
family (i.e. distinct from PF_OOB
) attempts to shutdown a
socket
bearing the SOCK_OOB
flag, allowing the companion core to act upon
the same event as it sees fit. At the moment, this call is issued by
the PF_INET
domain only. sock_oob_shutdown() runs after the regular shutdown actions for
the domain has succeeded, but before the associated INET socket is
released.
The address of the INET socket descriptor to shutdown.
The type of shutdown process, among SHUT_RD
(shut down the receive
side only), SHUT_WR
(shut down the send side only), or SHUT_RDWR
(shut down both receive and send sides).
This routine is called for a socket bearing the SOCK_OOB
flag, for
which the in-band network stack has successfully handled a connection
request.
The address of the INET socket descriptor to attach to the companion core.
This routine should return zero on success, or a negative errno status. Any error binding the socket on the out-of-band side causes the whole connection request to fail, including the in-band connection.
This hook should be implemented by the companion core in order to receive IOCTL requests which should be handled from the out-of-band execution stage. The receiving end is a file associated to a BSD socket.
The address of the struct file
descriptor associated to a BSD socket
for which an IOCTL request is received from the out-of-band execution
stage.
This routine should return zero on success, or a negative errno status.
This hook should implement a redirector of IOCTL
requests for
in-band protocols (i.e. distinct from PF_OOB
) for which an
out-of-band extension exists. In this case, the hook implemented by
the companion core interposes on the normal handling of IOCTL
commands, falling back to the regular IOCTL command handler unless the
companion core handled it successfully.
The address of the INET socket descriptor for which an IOCTL request is being redirected.
This routine should return zero on success, or a negated errno code. On success, the request is not passed to the regular IOCTL command handler. Otherwise, if the out-of-band protocol implementation was not able to handle the IOCTL command, it should return -ENOIOCTLCMD to the caller, so that the latter passes it on to the regular IOCTL command handler.