Skip to content

Commit ffffc93

Browse files
committed
[tailscale1.17] net: reduce allocations for UDP send/recv on Windows
This brings the optimizations added in CLs 331489 and 331490 to Windows. Updates golang#43451 (cherry picked from golang.org/cl/331511) Change-Id: I75cf520050325d9eb5c2785d6d8677cc864fcac8
1 parent 65f981c commit ffffc93

File tree

3 files changed

+122
-4
lines changed

3 files changed

+122
-4
lines changed

api/go1.tailscale.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,7 @@ pkg syscall (openbsd-amd64-cgo), func RecvfromInet4(int, []uint8, int, *Sockaddr
106106
pkg syscall (openbsd-amd64-cgo), func RecvfromInet6(int, []uint8, int, *SockaddrInet6) (int, error)
107107
pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
108108
pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
109+
pkg syscall (windows-386), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error
110+
pkg syscall (windows-386), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error
111+
pkg syscall (windows-amd64), func WSASendtoInet4(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet4, *Overlapped, *uint8) error
112+
pkg syscall (windows-amd64), func WSASendtoInet6(Handle, *WSABuf, uint32, *uint32, uint32, SockaddrInet6, *Overlapped, *uint8) error

src/internal/poll/fd_windows.go

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ type operation struct {
7979
buf syscall.WSABuf
8080
msg windows.WSAMsg
8181
sa syscall.Sockaddr
82+
sa4 syscall.SockaddrInet4
83+
sa6 syscall.SockaddrInet6
8284
rsa *syscall.RawSockaddrAny
8385
rsan int32
8486
handle syscall.Handle
@@ -595,7 +597,30 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
595597

596598
// ReadFrom wraps the recvfrom network call for IPv4.
597599
func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) {
598-
n, sa, err := fd.ReadFrom(buf)
600+
if len(buf) == 0 {
601+
return 0, nil
602+
}
603+
if len(buf) > maxRW {
604+
buf = buf[:maxRW]
605+
}
606+
if err := fd.readLock(); err != nil {
607+
return 0, err
608+
}
609+
defer fd.readUnlock()
610+
o := &fd.rop
611+
o.InitBuf(buf)
612+
n, err := execIO(o, func(o *operation) error {
613+
if o.rsa == nil {
614+
o.rsa = new(syscall.RawSockaddrAny)
615+
}
616+
o.rsan = int32(unsafe.Sizeof(*o.rsa))
617+
return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
618+
})
619+
err = fd.eofError(n, err)
620+
if err != nil {
621+
return n, err
622+
}
623+
sa, _ := o.rsa.Sockaddr()
599624
if sa != nil {
600625
*sa4 = *(sa.(*syscall.SockaddrInet4))
601626
}
@@ -604,7 +629,30 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error)
604629

605630
// ReadFrom wraps the recvfrom network call for IPv6.
606631
func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) {
607-
n, sa, err := fd.ReadFrom(buf)
632+
if len(buf) == 0 {
633+
return 0, nil
634+
}
635+
if len(buf) > maxRW {
636+
buf = buf[:maxRW]
637+
}
638+
if err := fd.readLock(); err != nil {
639+
return 0, err
640+
}
641+
defer fd.readUnlock()
642+
o := &fd.rop
643+
o.InitBuf(buf)
644+
n, err := execIO(o, func(o *operation) error {
645+
if o.rsa == nil {
646+
o.rsa = new(syscall.RawSockaddrAny)
647+
}
648+
o.rsan = int32(unsafe.Sizeof(*o.rsa))
649+
return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil)
650+
})
651+
err = fd.eofError(n, err)
652+
if err != nil {
653+
return n, err
654+
}
655+
sa, _ := o.rsa.Sockaddr()
608656
if sa != nil {
609657
*sa6 = *(sa.(*syscall.SockaddrInet6))
610658
}
@@ -810,8 +858,42 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
810858
}
811859

812860
// WriteTo wraps the sendto network call for IPv4.
813-
func (fd *FD) WriteToInet4(buf []byte, sa syscall.SockaddrInet4) (int, error) {
814-
return fd.WriteTo(buf, &sa)
861+
func (fd *FD) WriteToInet4(buf []byte, sa4 syscall.SockaddrInet4) (int, error) {
862+
if err := fd.writeLock(); err != nil {
863+
return 0, err
864+
}
865+
defer fd.writeUnlock()
866+
867+
if len(buf) == 0 {
868+
// handle zero-byte payload
869+
o := &fd.wop
870+
o.InitBuf(buf)
871+
o.sa4 = sa4
872+
n, err := execIO(o, func(o *operation) error {
873+
return syscall.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil)
874+
})
875+
return n, err
876+
}
877+
878+
ntotal := 0
879+
for len(buf) > 0 {
880+
b := buf
881+
if len(b) > maxRW {
882+
b = b[:maxRW]
883+
}
884+
o := &fd.wop
885+
o.InitBuf(b)
886+
o.sa4 = sa4
887+
n, err := execIO(o, func(o *operation) error {
888+
return syscall.WSASendtoInet4(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa4, &o.o, nil)
889+
})
890+
ntotal += int(n)
891+
if err != nil {
892+
return ntotal, err
893+
}
894+
buf = buf[n:]
895+
}
896+
return ntotal, nil
815897
}
816898

817899
// WriteTo wraps the sendto network call for IPv6.

src/syscall/syscall_windows.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,38 @@ func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32
924924
return err
925925
}
926926

927+
func WSASendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) {
928+
rsa, len, err := to.sockaddr()
929+
if err != nil {
930+
return err
931+
}
932+
r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
933+
if r1 == socket_error {
934+
if e1 != 0 {
935+
err = errnoErr(e1)
936+
} else {
937+
err = EINVAL
938+
}
939+
}
940+
return err
941+
}
942+
943+
func WSASendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) {
944+
rsa, len, err := to.sockaddr()
945+
if err != nil {
946+
return err
947+
}
948+
r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
949+
if r1 == socket_error {
950+
if e1 != 0 {
951+
err = errnoErr(e1)
952+
} else {
953+
err = EINVAL
954+
}
955+
}
956+
return err
957+
}
958+
927959
func LoadGetAddrInfo() error {
928960
return procGetAddrInfoW.Find()
929961
}

0 commit comments

Comments
 (0)