diff --git a/net/tstun/wrap.go b/net/tstun/wrap.go index c9b616582..0574fc9e7 100644 --- a/net/tstun/wrap.go +++ b/net/tstun/wrap.go @@ -315,7 +315,7 @@ func (t *Wrapper) poll() { if t.isClosed() { return } - n, err = t.tdev.Read(t.buffer[:], PacketStartOffset) + n, err = t.read(t.buffer[:], PacketStartOffset) } t.sendOutbound(tunReadResult{data: t.buffer[PacketStartOffset : PacketStartOffset+n], err: err}) } @@ -565,6 +565,21 @@ func (t *Wrapper) write(buf []byte, offset int) (int, error) { return n, err } +func (t *Wrapper) read(buf []byte, offset int) (n int, err error) { + // TODO: upstream has graceful shutdown error handling here. + buff := buf[offset-4:] + n, err = t.ring.Read(buff[:]) + if errors.Is(err, syscall.EBADFD) { + err = os.ErrClosed + } + if n < 4 { + n = 0 + } else { + n -= 4 + } + return +} + func (t *Wrapper) GetFilter() *filter.Filter { filt, _ := t.filter.Load().(*filter.Filter) return filt diff --git a/net/uring/io_uring_linux.go b/net/uring/io_uring_linux.go index d86a304c0..55e215a6e 100644 --- a/net/uring/io_uring_linux.go +++ b/net/uring/io_uring_linux.go @@ -343,7 +343,7 @@ type fileReq struct { // Read data into buf[offset:]. // We are allowed to write junk into buf[offset-4:offset]. -func (u *File) Read(buf []byte, offset int) (n int, err error) { // read a packet from the device (without any additional headers) +func (u *File) Read(buf []byte) (n int, err error) { // read a packet from the device (without any additional headers) if u.fd == 0 { return 0, errors.New("invalid uring.File") } @@ -353,10 +353,8 @@ func (u *File) Read(buf []byte, offset int) (n int, err error) { // read a packe return 0, fmt.Errorf("Read: %v", err) } r := u.readReqs[idx] - // Ignore the first 4 bytes of r.buf, because it contains TUN IP header, which we don't use. - // TODO: open with NOPI? rbuf := sliceOf(r.buf, n) - n = copy(buf[offset:], rbuf[4:]) + copy(buf, rbuf) // Queue up a new request. err = u.submitReadvRequest(int(idx)) if err != nil { @@ -406,6 +404,7 @@ func (u *File) Write(buf []byte) (int, error) { func (u *File) Close() error { u.close.Do(func() { u.file.Close() + // TODO: require kernel 5.5, send an abort SQE, handle aborts gracefully C.io_uring_queue_exit(u.readRing) C.io_uring_queue_exit(u.writeRing) u.readRing = nil