Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opcode: add RecvMsgMulti #201

Merged
merged 6 commits into from
Feb 19, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions io-uring-test/src/tests/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1292,16 +1292,11 @@ pub fn test_udp_recvmsg_multishot<S: squeue::EntryMarker, C: cqueue::EntryMarker
msghdr.msg_namelen = 32;
msghdr.msg_controllen = 0;

// TODO(lucab): make this more ergonomic to use.
const IORING_RECV_MULTISHOT: u16 = 2;

let recvmsg_e = io_uring::opcode::RecvMsg::new(socket_slot, &mut msghdr as *mut _)
.ioprio(IORING_RECV_MULTISHOT)
.buf_group(BUF_GROUP)
.build()
.flags(io_uring::squeue::Flags::BUFFER_SELECT)
.user_data(77)
.into();
let recvmsg_e =
io_uring::opcode::RecvMsgMulti::new(socket_slot, &mut msghdr as *mut _, BUF_GROUP)
.build()
.user_data(77)
.into();
unsafe { ring.submission().push(&recvmsg_e)? };
ring.submitter().submit().unwrap();

Expand Down
66 changes: 65 additions & 1 deletion src/opcode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,58 @@ opcode!(
}
);

opcode!(
/// Receive multiple messages on a socket, equivalent to `recvmsg(2)`.
///
/// Parameters:
/// msg: For this multishot variant of ResvMsg, only the msg_namelen and msg_controllen
/// fields are relevant.
/// buf_group: The id of the provided buffer pool to use for each received message.
///
/// See also the description of [`SendMsg`] and [`types::RecvMsgOut`].
///
/// The multishot version allows the application to issue a single receive request, which
/// repeatedly posts a CQE when data is available. It requires the MSG_WAITALL flag is not set.
/// Each CQE will take a buffer out of a provided buffer pool for receiving. The application
/// should check the flags of each CQE, regardless of its result. If a posted CQE does not have
/// the IORING_CQE_F_MORE flag set then the multishot receive will be done and the application
/// should issue a new request.
///
/// Unlike [`RecvMsg`], this multishot recvmsg will prepend a struct which describes the layout
/// of the rest of the buffer in combination with the initial msghdr structure submitted with
/// the request. Use [`types::RecvMsgOut`] to parse the data received and access its
/// components.
///
/// The recvmsg multishot variant is available since kernel 6.0.

#[derive(Debug)]
quininer marked this conversation as resolved.
Show resolved Hide resolved
pub struct RecvMsgMulti {
fd: { impl sealed::UseFixed },
msg: { *mut libc::msghdr },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this doesn't strictly need to be mut.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thanks.

buf_group: { u16 },
;;
ioprio: u16 = 0,
flags: u32 = 0
}

pub const CODE = sys::IORING_OP_RECVMSG;

pub fn build(self) -> Entry {
let RecvMsgMulti { fd, msg, buf_group, ioprio, flags } = self;

let mut sqe = sqe_zeroed();
sqe.opcode = Self::CODE;
assign_fd!(sqe.fd = fd);
sqe.__bindgen_anon_2.addr = msg as _;
sqe.len = 1;
sqe.__bindgen_anon_3.msg_flags = flags;
sqe.__bindgen_anon_4.buf_group = buf_group;
sqe.flags |= 1 << sys::IOSQE_BUFFER_SELECT_BIT;
sqe.ioprio = ioprio | (sys::IORING_RECV_MULTISHOT as u16);
Entry(sqe)
}
);

opcode!(
/// Register a timeout operation.
///
Expand Down Expand Up @@ -1100,7 +1152,19 @@ opcode!(
opcode!(
/// Receive multiple messages from a socket, equivalent to `recv(2)`.
///
/// Parameter:
/// buf_group: The id of the provided buffer pool to use for each received message.
///
/// MSG_WAITALL should not be set in flags.
///
/// The multishot version allows the application to issue a single receive request, which
/// repeatedly posts a CQE when data is available. Each CQE will take a buffer out of a
/// provided buffer pool for receiving. The application should check the flags of each CQE,
/// regardless of its result. If a posted CQE does not have the IORING_CQE_F_MORE flag set then
/// the multishot receive will be done and the application should issue a new request.
///
/// Multishot variants are available since kernel 6.0.

pub struct RecvMulti {
fd: { impl sealed::UseFixed },
buf_group: { u16 },
Expand All @@ -1118,7 +1182,7 @@ opcode!(
assign_fd!(sqe.fd = fd);
sqe.__bindgen_anon_3.msg_flags = flags as _;
sqe.__bindgen_anon_4.buf_group = buf_group;
sqe.flags = 1 << sys::IOSQE_BUFFER_SELECT_BIT;
sqe.flags |= 1 << sys::IOSQE_BUFFER_SELECT_BIT;
sqe.ioprio = sys::IORING_RECV_MULTISHOT as _;
Entry(sqe)
}
Expand Down