mbox series

[RFC,net,0/8] rxrpc: Multiqueue, sendfile, splice and call security

Message ID 165599093190.1827880.6407599132975295152.stgit@warthog.procyon.org.uk (mailing list archive)
Headers show
Series rxrpc: Multiqueue, sendfile, splice and call security | expand

Message

David Howells June 23, 2022, 1:28 p.m. UTC
Here are some patches to provide support for multiqueuing, sendfile and
splice on AF_RXRPC sockets and to allow calls to have individual security
settings:

 (1) Multiqueue support is provided in the sense that a number of AF_RXRPC
     sockets can be bound together such that they share a UDP socket, all
     listen on the same set of services and share a queue of as-yet
     unaccepted calls.

     This is done by creating a socket and setting it up to listen:

	fd1 = socket(AF_RXRPC, SOCK_DGRAM, IPPROTO_IPV6);
	bind(fd1, &address);
	listen(fd1, depth);

     then creating one or more additional sockets and binding them onto the
     first:

	fd2 = socket(AF_RXRPC, SOCK_DGRAM, IPPROTO_IPV6);
	setsockopt(fd2, SOL_RXRPC, RXRPC_BIND_CHANNEL, &fd1, sizeof(fd1));

     The sockets are then indistinguishable interfaces onto the local
     endpoint.  Note that each has its own non-overlapping set of user call
     IDs (tags passed in sendmsg/recvmsg control messages to indicate which
     call is being referred to).  This allows each socket to be used in a
     separate process with unshared VMs (pointers to management structs can
     be used as user call IDs).

     User call IDs can then be charged separately on each socket, as
     before:

	msg.msg_control	= control;
	msg.msg_controllen = ctrllen;
	RXRPC_ADD_CALLID(control, ctrllen, user_id);
	RXRPC_ADD_CHARGE_ACCEPT(control, ctrllen);
	ret = sendmsg(service, &msg, 0);

     If there are any user call IDs available on a particular socket,
     recvmsg() on that socket will pop a waiting call off the shared accept
     queue, tag it with the first ID and add it to the back of that
     socket's recvmsg queue.  From that point, that call can only be
     interacted with through that socket.  The same goes for client calls -
     they're bound to the socket they're started on.

     This allows a server to set up a pool of individual processes, each
     with a "copy" of the socket, with the kernel routing incoming calls as
     the processes announce their availabilty by providing a user ID.

 (2) Provide sendfile() support by allowing a call to be nominated through
     a sockopt as the target.  The call must be bound to that socket.  This
     is done by something like:

	setsockopt(client, SOL_RXRPC, RXRPC_SELECT_CALL_FOR_SEND,
		   &call_id, sizeof(call_id));
	sendfile(client, source, &pos, st.st_size);

     The target call is cleared when the call completion message is
     collected by recvmsg() or the sockopt is altered.  Setting 0 just
     clears it.  If no call is set, sendfile will fail.

 (3) Provide splice-read support by allowing a call to be nominated through
     a sockopt as the source.  The call must be bound to that socket.  This
     is done by something like:

	setsockopt(client, SOL_RXRPC, RXRPC_SELECT_CALL_FOR_RECV,
		   &call_id, sizeof(call_id));
	ret = splice(client, NULL, pipefd[1], NULL, count, 0);

     The source call is cleared when the call completion message is
     collected by recvmsg() or the sockopt is altered.  Setting 0 just
     clears it.  If no call is set, splice will fail.

 (4) Also limit recvmsg() by setting RXRPC_SELECT_CALL_FOR_RECV.  It will
     ignore other calls whilst it is effect.  The effect will be cancelled
     when the completion message is returned (MSG_EOR will be set).

 (5) Add two new control messages that can be passed to sendmsg() when
     initiating a client call to allow them to have authentication and
     crypto parameters individually set:

	RXRPC_SET_SECURITY_KEY
	RXRPC_SET_SECURITY_LEVEL

     The first allows a key to be specified to indicate the authentication
     and crypto; the second indicates the level of crypto required on the
     packet.

     Currently RXRPC_SET_SECURITY_KEY takes a key description, which it
     passes to request_key(), but possibly it should at least allow a key
     ID instead.

The patches can be found here also:

	http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-multiqueue

David
---
David Howells (8):
      rxrpc: List open sockets in /proc/net/rxrpc/sockets
      rxrpc: Allow UDP socket sharing for AF_RXRPC service sockets
      rxrpc: Allow multiple AF_RXRPC sockets to be bound together to form queues
      rxrpc: Allow the call to interact with to be preselected
      rxrpc: Implement sendfile() support
      rxrpc: Use selected call in recvmsg()
      rxrpc: Implement splice-read for rxrpc calls
      rxrpc: Set call security params in sendmsg() cmsg


 fs/afs/internal.h            |   3 -
 fs/afs/main.c                |   1 -
 fs/afs/rxrpc.c               |  83 +++---
 include/net/af_rxrpc.h       |   9 +-
 include/trace/events/afs.h   |   4 +
 include/trace/events/rxrpc.h |   9 +-
 include/uapi/linux/rxrpc.h   |   5 +
 net/rxrpc/af_rxrpc.c         | 510 ++++++++++++++++++++++++++++++-----
 net/rxrpc/ar-internal.h      | 112 +++++---
 net/rxrpc/call_accept.c      | 439 +++++++++++++++++++-----------
 net/rxrpc/call_object.c      | 133 +++++----
 net/rxrpc/conn_service.c     |  17 +-
 net/rxrpc/input.c            |  25 +-
 net/rxrpc/key.c              |  30 ++-
 net/rxrpc/local_object.c     |  24 +-
 net/rxrpc/net_ns.c           |   5 +
 net/rxrpc/peer_object.c      |  17 +-
 net/rxrpc/proc.c             | 120 ++++++++-
 net/rxrpc/recvmsg.c          | 330 ++++++++++++++++++++---
 net/rxrpc/security.c         |  22 +-
 net/rxrpc/sendmsg.c          |  78 +++++-
 net/rxrpc/server_key.c       |  12 +-
 22 files changed, 1524 insertions(+), 464 deletions(-)