diff --git a/net/uring/io_uring.c b/net/uring/io_uring.c index 5f8b4a099..13eec5094 100644 --- a/net/uring/io_uring.c +++ b/net/uring/io_uring.c @@ -18,6 +18,19 @@ typedef struct io_uring go_uring; typedef struct msghdr go_msghdr; typedef struct iovec go_iovec; typedef struct sockaddr_in go_sockaddr_in; +typedef struct io_uring_params go_io_uring_params; + +static int initialize(struct io_uring *ring, int fd) { + struct io_uring_params params; + memset(¶ms, 0, sizeof(params)); + params.flags |= IORING_SETUP_SQPOLL; + params.sq_thread_idle = 1000; // 1s + io_uring_queue_init_params(16, ring, ¶ms); // 16: size of ring + int ret; + ret = io_uring_register_files(ring, &fd, 1); + // TODO: Do we need to unregister files on close, or is Closing the uring enough? + return ret; +} // Wait for a completion to be available, fetch the data static uint64_t receive_into(struct io_uring *ring) { @@ -62,7 +75,7 @@ static uint16_t port(struct sockaddr_in *sa) { // submit a recvmsg request via liburing // TODO: What recvfrom support arrives, maybe use that instead? -static int submit_recvmsg_request(int sock, struct io_uring *ring, struct msghdr *mhdr, struct iovec *iov, struct sockaddr_in *sender, char *buf, int buflen, size_t idx) { +static int submit_recvmsg_request(struct io_uring *ring, struct msghdr *mhdr, struct iovec *iov, struct sockaddr_in *sender, char *buf, int buflen, size_t idx) { iov->iov_base = buf; iov->iov_len = buflen; @@ -73,7 +86,8 @@ static int submit_recvmsg_request(int sock, struct io_uring *ring, struct msghdr mhdr->msg_namelen = sizeof(struct sockaddr_in); struct io_uring_sqe *sqe = io_uring_get_sqe(ring); - io_uring_prep_recvmsg(sqe, sock, mhdr, 0); + io_uring_prep_recvmsg(sqe, 0, mhdr, 0); // use the 0th file in the list of registered fds + io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE); io_uring_sqe_set_data(sqe, (void *)(idx)); io_uring_submit(ring); diff --git a/net/uring/io_uring_linux.go b/net/uring/io_uring_linux.go index 44ff4be09..003b02164 100644 --- a/net/uring/io_uring_linux.go +++ b/net/uring/io_uring_linux.go @@ -56,13 +56,16 @@ func NewUDPConn(conn *net.UDPConn) (*UDPConn, error) { } r := new(C.go_uring) - const queue_depth = 16 // TODO: What value to use here? - C.io_uring_queue_init(queue_depth, r, 0) + fd := C.int(file.Fd()) + ret := C.initialize(r, fd) + if ret < 0 { + return nil, fmt.Errorf("uring initialization failed: %d", ret) + } u := &UDPConn{ ptr: r, conn: conn, file: file, - fd: C.int(file.Fd()), + fd: fd, local: conn.LocalAddr(), } for i := range u.reqs { @@ -84,7 +87,7 @@ type req struct { func (u *UDPConn) submitRequest(idx int) error { r := &u.reqs[idx] // TODO: make a C struct instead of a Go struct, and pass that in, to simplify call sites. - errno := C.submit_recvmsg_request(u.fd, u.ptr, &r.mhdr, &r.iov, &r.sa, (*C.char)(unsafe.Pointer(&r.buf[0])), C.int(len(r.buf)), C.size_t(idx)) + errno := C.submit_recvmsg_request(u.ptr, &r.mhdr, &r.iov, &r.sa, (*C.char)(unsafe.Pointer(&r.buf[0])), C.int(len(r.buf)), C.size_t(idx)) if errno < 0 { return fmt.Errorf("uring.submitRequest failed: %v", errno) // TODO: Improve } @@ -96,8 +99,8 @@ func (u *UDPConn) ReadFromNetaddr(buf []byte) (int, netaddr.IPPort, error) { return 0, netaddr.IPPort{}, errors.New("invalid uring.UDPConn") } nidx := C.receive_into(u.ptr) - if int64(nidx) == -1 { - return 0, netaddr.IPPort{}, errors.New("something wrong") + if int64(nidx) < 0 { + return 0, netaddr.IPPort{}, fmt.Errorf("something wrong, errno %v", int64(nidx)) } idx := uint32(nidx) n := uint32(nidx >> 32)