mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 00:08:56 +00:00
io_uring: add setsockopt/getsockopt
ring.cmd_sock is generic socket operation. Two most common uses are setsockopt and getsockopt. This provides same interface as posix versions of this methods. libring has also [sqe_set_flags](https://man7.org/linux/man-pages/man3/io_uring_sqe_set_flags.3.html) method. Adding that in our io_uring_sqe. Adding sqe.link_next method for setting most common flag.
This commit is contained in:
parent
d98c0893b0
commit
4df039d235
@ -6154,6 +6154,7 @@ pub const io_uring_probe = extern struct {
|
||||
resv2: [3]u32,
|
||||
ops: [256]io_uring_probe_op,
|
||||
|
||||
/// Is the operation supported on the running kernel.
|
||||
pub fn is_supported(self: @This(), op: IORING_OP) bool {
|
||||
const i = @intFromEnum(op);
|
||||
if (i > @intFromEnum(self.last_op) or i >= self.ops_len)
|
||||
|
||||
@ -1399,15 +1399,18 @@ pub fn listen(
|
||||
return sqe;
|
||||
}
|
||||
|
||||
fn cmd_sock(
|
||||
/// Prepares an cmd request for a socket.
|
||||
/// See: https://man7.org/linux/man-pages/man3/io_uring_prep_cmd.3.html
|
||||
/// Available since 6.7.
|
||||
pub fn cmd_sock(
|
||||
self: *IoUring,
|
||||
user_data: u64,
|
||||
cmd_op: linux.IO_URING_SOCKET_OP,
|
||||
fd: linux.fd_t,
|
||||
level: u32,
|
||||
optname: u32,
|
||||
optval: u64,
|
||||
optlen: u32,
|
||||
level: u32, // linux.SOL
|
||||
optname: u32, // linux.SO
|
||||
optval: u64, // pointer to the option value
|
||||
optlen: u32, // size of the option value
|
||||
) !*linux.io_uring_sqe {
|
||||
const sqe = try self.get_sqe();
|
||||
sqe.prep_cmd_sock(cmd_op, fd, level, optname, optval, optlen);
|
||||
@ -1415,6 +1418,50 @@ fn cmd_sock(
|
||||
return sqe;
|
||||
}
|
||||
|
||||
/// Prepares set socket option for the optname argument, at the protocol
|
||||
/// level specified by the level argument.
|
||||
/// Available since 6.7.n
|
||||
pub fn setsockopt(
|
||||
self: *IoUring,
|
||||
user_data: u64,
|
||||
fd: linux.fd_t,
|
||||
level: u32, // linux.SOL
|
||||
optname: u32, // linux.SO
|
||||
opt: []const u8,
|
||||
) !*linux.io_uring_sqe {
|
||||
return try self.cmd_sock(
|
||||
user_data,
|
||||
.SETSOCKOPT,
|
||||
fd,
|
||||
level,
|
||||
optname,
|
||||
@intFromPtr(opt.ptr),
|
||||
@intCast(opt.len),
|
||||
);
|
||||
}
|
||||
|
||||
/// Prepares get socket option to retrieve the value for the option specified by
|
||||
/// the option_name argument for the socket specified by the fd argument.
|
||||
/// Available since 6.7.
|
||||
pub fn getsockopt(
|
||||
self: *IoUring,
|
||||
user_data: u64,
|
||||
fd: linux.fd_t,
|
||||
level: u32, // linux.SOL
|
||||
optname: u32, // linux.SO
|
||||
opt: []u8,
|
||||
) !*linux.io_uring_sqe {
|
||||
return try self.cmd_sock(
|
||||
user_data,
|
||||
.GETSOCKOPT,
|
||||
fd,
|
||||
level,
|
||||
optname,
|
||||
@intFromPtr(opt.ptr),
|
||||
@intCast(opt.len),
|
||||
);
|
||||
}
|
||||
|
||||
pub const SubmissionQueue = struct {
|
||||
head: *u32,
|
||||
tail: *u32,
|
||||
@ -4391,13 +4438,10 @@ test "bind/listen/connect" {
|
||||
try testing.expect(listen_fd > 2);
|
||||
|
||||
// Prepare: set socket option * 2, bind, listen
|
||||
var sock_opt: u32 = 1;
|
||||
var sqe = try ring.cmd_sock(2, .SETSOCKOPT, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, @intFromPtr(&sock_opt), @sizeOf(u32));
|
||||
sqe.flags |= linux.IOSQE_IO_LINK;
|
||||
sqe = try ring.cmd_sock(3, .SETSOCKOPT, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEPORT, @intFromPtr(&sock_opt), @sizeOf(u32));
|
||||
sqe.flags |= linux.IOSQE_IO_LINK;
|
||||
sqe = try ring.bind(4, listen_fd, &addr.any, addr.getOsSockLen(), 0);
|
||||
sqe.flags |= linux.IOSQE_IO_LINK;
|
||||
var optval: u32 = 1;
|
||||
(try ring.setsockopt(2, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, mem.asBytes(&optval))).link_next();
|
||||
(try ring.setsockopt(3, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEPORT, mem.asBytes(&optval))).link_next();
|
||||
(try ring.bind(4, listen_fd, &addr.any, addr.getOsSockLen(), 0)).link_next();
|
||||
_ = try ring.listen(5, listen_fd, 1, 0);
|
||||
// Submit 4 operations
|
||||
try testing.expectEqual(4, try ring.submit());
|
||||
@ -4409,13 +4453,13 @@ test "bind/listen/connect" {
|
||||
}
|
||||
|
||||
// Check that socket option is set
|
||||
sock_opt = 0xff;
|
||||
_ = try ring.cmd_sock(5, .GETSOCKOPT, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, @intFromPtr(&sock_opt), @sizeOf(u32));
|
||||
optval = 0;
|
||||
_ = try ring.getsockopt(5, listen_fd, linux.SOL.SOCKET, linux.SO.REUSEADDR, mem.asBytes(&optval));
|
||||
try testing.expectEqual(1, try ring.submit());
|
||||
cqe = try ring.copy_cqe();
|
||||
try testing.expectEqual(5, cqe.user_data);
|
||||
try testing.expectEqual(posix.E.SUCCESS, cqe.err());
|
||||
try testing.expectEqual(1, sock_opt);
|
||||
try testing.expectEqual(1, optval);
|
||||
|
||||
// Read system assigned port into addr
|
||||
var addr_len: posix.socklen_t = addr.getOsSockLen();
|
||||
@ -4460,8 +4504,7 @@ test "bind/listen/connect" {
|
||||
|
||||
// Shutdown and close all sockets
|
||||
for ([_]posix.socket_t{ connect_fd, accept_fd, listen_fd }) |fd| {
|
||||
var sqe = try ring.shutdown(9, fd, posix.SHUT.RDWR);
|
||||
sqe.flags |= linux.IOSQE_IO_LINK;
|
||||
(try ring.shutdown(9, fd, posix.SHUT.RDWR)).link_next();
|
||||
_ = try ring.close(10, fd);
|
||||
try testing.expectEqual(2, try ring.submit());
|
||||
for (0..2) |i| {
|
||||
@ -4477,8 +4520,7 @@ fn testSendRecv(ring: *IoUring, send_fd: posix.socket_t, recv_fd: posix.socket_t
|
||||
var buffer_recv: [buffer_send.len * 2]u8 = undefined;
|
||||
|
||||
// 2 sends
|
||||
var sqe = try ring.send(1, send_fd, buffer_send, linux.MSG.WAITALL);
|
||||
sqe.flags |= linux.IOSQE_IO_LINK;
|
||||
_ = try ring.send(1, send_fd, buffer_send, linux.MSG.WAITALL);
|
||||
_ = try ring.send(2, send_fd, buffer_send, linux.MSG.WAITALL);
|
||||
try testing.expectEqual(2, try ring.submit());
|
||||
for (0..2) |i| {
|
||||
|
||||
@ -666,4 +666,14 @@ pub const io_uring_sqe = extern struct {
|
||||
// addr3 is overloaded, https://github.com/axboe/liburing/blob/e1003e496e66f9b0ae06674869795edf772d5500/src/include/liburing/io_uring.h#L102
|
||||
sqe.addr3 = optval;
|
||||
}
|
||||
|
||||
pub fn set_flags(sqe: *linux.io_uring_sqe, flags: u8) void {
|
||||
sqe.flags |= flags;
|
||||
}
|
||||
|
||||
/// This SQE forms a link with the next SQE in the submission ring. Next SQE
|
||||
/// will not be started before this one completes. Forms a chain of SQEs.
|
||||
pub fn link_next(sqe: *linux.io_uring_sqe) void {
|
||||
sqe.flags |= linux.IOSQE_IO_LINK;
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user