net/uring: add go ntohs

Instead of calling out to C for ntohs, just implement it in Go for effiency.

Signed-off-by: kadmin <julianknodt@gmail.com>
This commit is contained in:
kadmin 2021-07-07 23:48:52 +00:00 committed by Josh Bleecher Snyder
parent cc5c696834
commit 61e3d919ef
4 changed files with 76 additions and 7 deletions

View File

@ -21,6 +21,7 @@ import (
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
"inet.af/netaddr"
"tailscale.com/util/endian"
)
const bufferSize = device.MaxSegmentSize
@ -183,10 +184,10 @@ func (u *UDPConn) ReadFromNetaddr(buf []byte) (int, netaddr.IPPort, error) {
// TODO: native go endianness conversion routines so we don't have to call ntohl, etc.
if u.is4 {
ip = netaddr.IPFrom4(*(*[4]byte)((unsafe.Pointer)((&r.sa.sin_addr.s_addr))))
port = uint16(C.ntohs(r.sa.sin_port))
port = endian.Ntoh16(uint16(r.sa.sin_port))
} else {
ip = netaddr.IPFrom16(*(*[16]byte)((unsafe.Pointer)((&r.sa6.sin6_addr))))
port = uint16(C.ntohs(r.sa6.sin6_port))
port = endian.Ntoh16(uint16(r.sa6.sin6_port))
}
ipp := netaddr.IPPortFrom(ip, port)
rbuf := sliceOf(r.buf, n)
@ -296,16 +297,15 @@ func (u *UDPConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
copy(rbuf, p)
if u.is4 {
// TODO: native go endianness conversion routines so we don't have to call ntohl, etc.
ipu32 := binary.BigEndian.Uint32(udpAddr.IP)
r.sa.sin_addr.s_addr = C.htonl(C.uint32_t(ipu32))
r.sa.sin_port = C.htons(C.uint16_t(udpAddr.Port))
r.sa.sin_addr.s_addr = C.uint32_t(endian.Hton32(ipu32))
r.sa.sin_port = C.uint16_t(endian.Hton16(uint16(udpAddr.Port)))
r.sa.sin_family = C.AF_INET
} else {
dst := (*[16]byte)((unsafe.Pointer)(&r.sa6.sin6_addr))
src := (*[16]byte)((unsafe.Pointer)(&udpAddr.IP[0]))
*dst = *src
r.sa6.sin6_port = C.htons(C.uint16_t(udpAddr.Port))
r.sa6.sin6_port = C.uint16_t(endian.Hton16(uint16(udpAddr.Port)))
r.sa6.sin6_family = C.AF_INET6
}
C.submit_sendmsg_request(

View File

@ -13,3 +13,12 @@ const Big = true
// Native is the platform's native byte order.
var Native = binary.BigEndian
// Ntoh16 converts network order into native/host.
func Ntoh16(v uint16) uint16 { return v }
// Hton32 converts native/host uint32 order into network order.
func Hton32(v uint32) uint32 { return v }
// Hton16 converts native/host uint16 order into network order.
func Hton16(v uint16) uint16 { return v }

View File

@ -0,0 +1,48 @@
package endian
import (
"encoding/binary"
"testing"
"unsafe"
)
func TestNtoh16(t *testing.T) {
raw := uint16(0xABCD)
rawBytes := toNativeBytes16(raw)
big := binary.BigEndian.Uint16(rawBytes[:])
if raw != Ntoh16(big) {
t.Errorf("ntohs failed, want %v, got %v", raw, Ntoh16(big))
}
}
func toNativeBytes32(v uint32) [4]byte {
return *(*[4]byte)(unsafe.Pointer(&v))
}
func TestHton32(t *testing.T) {
raw := uint32(0xDEADBEEF)
networkOrder := Hton32(raw)
bytes := toNativeBytes32(networkOrder)
fromBig := binary.BigEndian.Uint32(bytes[:])
if fromBig != raw {
t.Errorf("htonl failed, want %v, got %v", raw, fromBig)
}
}
func toNativeBytes16(v uint16) [2]byte {
return *(*[2]byte)(unsafe.Pointer(&v))
}
func TestHton16(t *testing.T) {
raw := uint16(0xBEEF)
networkOrder := Hton16(raw)
bytes := toNativeBytes16(networkOrder)
fromBig := binary.BigEndian.Uint16(bytes[:])
if fromBig != raw {
t.Errorf("htonl failed, want %v, got %v", raw, fromBig)
}
}

View File

@ -6,10 +6,22 @@
package endian
import "encoding/binary"
import (
"encoding/binary"
"math/bits"
)
// Big is whether the current platform is big endian.
const Big = false
// Native is the platform's native byte order.
var Native = binary.LittleEndian
// Ntoh16 converts network into native/host order.
func Ntoh16(v uint16) uint16 { return bits.ReverseBytes16(v) }
// Hton32 converts native/host uint32 order into network order.
func Hton32(v uint32) uint32 { return bits.ReverseBytes32(v) }
// Hton16 converts native/host uint16 order into network order.
func Hton16(v uint16) uint16 { return bits.ReverseBytes16(v) }