diff --git a/net/uring/io_uring.c b/net/uring/io_uring.c index b90d20628..73fdbfa4c 100644 --- a/net/uring/io_uring.c +++ b/net/uring/io_uring.c @@ -20,7 +20,7 @@ typedef struct iovec go_iovec; typedef struct sockaddr_in go_sockaddr_in; // Wait for a completion to be available, fetch the data -static int receive_into(int sock, struct io_uring *ring, char *ip, uint16_t *port) { +static int receive_into(struct io_uring *ring) { struct io_uring_cqe *cqe; again:; @@ -44,15 +44,18 @@ again:; return -1; } int n = cqe->res; - - struct sockaddr_in *sa = (void *)mhdr->msg_name; - memcpy(ip, &sa->sin_addr, 4); - *port = ntohs(sa->sin_port); - io_uring_cqe_seen(ring, cqe); return n; } +static uint32_t ip(struct sockaddr_in *sa) { + return ntohl(sa->sin_addr.s_addr); +} + +static uint16_t port(struct sockaddr_in *sa) { + return ntohs(sa->sin_port); +} + // 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) { diff --git a/net/uring/io_uring_linux.go b/net/uring/io_uring_linux.go index c0500d45a..ebe35f360 100644 --- a/net/uring/io_uring_linux.go +++ b/net/uring/io_uring_linux.go @@ -5,6 +5,7 @@ import "C" import ( + "encoding/binary" "errors" "fmt" "net" @@ -35,7 +36,7 @@ type UDPConn struct { file *os.File // must keep file from being GC'd fd C.int local net.Addr - req req + reqs [1]req } func NewUDPConn(conn *net.UDPConn) (*UDPConn, error) { @@ -64,9 +65,11 @@ func NewUDPConn(conn *net.UDPConn) (*UDPConn, error) { fd: C.int(file.Fd()), local: conn.LocalAddr(), } - if err := u.submitRequest(); err != nil { - u.Close() // TODO: will this crash? - return nil, err + for i := range u.reqs[:1] { + if err := u.submitRequest(&u.reqs[i]); err != nil { + u.Close() // TODO: will this crash? + return nil, err + } } return u, nil } @@ -75,14 +78,12 @@ type req struct { mhdr C.go_msghdr iov C.go_iovec sa C.go_sockaddr_in - ip [4]byte // TODO: ipv6 - port C.uint16_t buf [device.MaxSegmentSize]byte } -func (u *UDPConn) submitRequest() error { +func (u *UDPConn) submitRequest(r *req) error { // TODO: eventually separate submitting the request and waiting for the response. - errno := C.submit_recvmsg_request(u.fd, u.ptr, &u.req.mhdr, &u.req.iov, &u.req.sa, (*C.char)(unsafe.Pointer(&u.req.buf[0])), C.int(len(u.req.buf))) + 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))) if errno < 0 { return fmt.Errorf("uring.submitRequest failed: %v", errno) // TODO: Improve } @@ -93,14 +94,20 @@ func (u *UDPConn) ReadFromNetaddr(buf []byte) (int, netaddr.IPPort, error) { if u.fd == 0 { return 0, netaddr.IPPort{}, errors.New("invalid uring.UDPConn") } - n := C.receive_into(u.fd, u.ptr, (*C.char)(unsafe.Pointer(&u.req.ip)), &u.req.port) + r := &u.reqs[0] + n := C.receive_into(u.ptr) if n < 0 { return 0, netaddr.IPPort{}, errors.New("something wrong") } - ipp := netaddr.IPPortFrom(netaddr.IPFrom4(u.req.ip), uint16(u.req.port)) - copy(buf, u.req.buf[:n]) + // TODO: this is broken :((( + ip := C.ip(&r.sa) + var ip4 [4]byte + binary.BigEndian.PutUint32(ip4[:], uint32(ip)) + port := C.port(&r.sa) + ipp := netaddr.IPPortFrom(netaddr.IPFrom4(ip4), uint16(port)) + copy(buf, r.buf[:n]) // Queue up a new request. - err := u.submitRequest() + err := u.submitRequest(r) if err != nil { panic("how should we handle this?") }