mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
net/packet: remove {get,put}{16,32} indirection to encoding/binary.
name old time/op new time/op delta Decode/tcp4-8 28.8ns ± 2% 13.1ns ± 4% -54.44% (p=0.008 n=5+5) Decode/tcp6-8 20.6ns ± 1% 12.6ns ± 2% -38.72% (p=0.008 n=5+5) Decode/udp4-8 28.2ns ± 1% 12.1ns ± 4% -57.01% (p=0.008 n=5+5) Decode/udp6-8 20.0ns ± 6% 12.1ns ± 2% -39.38% (p=0.008 n=5+5) Decode/icmp4-8 21.7ns ± 2% 11.5ns ± 1% -47.01% (p=0.008 n=5+5) Decode/icmp6-8 14.1ns ± 2% 11.8ns ± 4% -16.60% (p=0.008 n=5+5) Decode/unknown-8 9.43ns ± 2% 9.30ns ± 3% ~ (p=0.222 n=5+5) Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
parent
55b1221db2
commit
22bf48f37c
@ -4,6 +4,8 @@
|
||||
|
||||
package packet
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
type ICMP4Type uint8
|
||||
|
||||
const (
|
||||
@ -66,7 +68,7 @@ func (h ICMP4Header) Marshal(buf []byte) error {
|
||||
|
||||
h.IP4Header.Marshal(buf)
|
||||
|
||||
put16(buf[22:24], ipChecksum(buf))
|
||||
binary.BigEndian.PutUint16(buf[22:24], ipChecksum(buf))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
package packet
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
@ -21,13 +22,13 @@ func NewIP4(b net.IP) IP4 {
|
||||
if b4 == nil {
|
||||
panic(fmt.Sprintf("To4(%v) failed", b))
|
||||
}
|
||||
return IP4(get32(b4))
|
||||
return IP4(binary.BigEndian.Uint32(b4))
|
||||
}
|
||||
|
||||
// IPFromNetaddr converts a netaddr.IP to an IP.
|
||||
func IP4FromNetaddr(ip netaddr.IP) IP4 {
|
||||
ipbytes := ip.As4()
|
||||
return IP4(get32(ipbytes[:]))
|
||||
return IP4(binary.BigEndian.Uint32(ipbytes[:]))
|
||||
}
|
||||
|
||||
// Netaddr converts an IP to a netaddr.IP.
|
||||
@ -71,16 +72,16 @@ func (h IP4Header) Marshal(buf []byte) error {
|
||||
|
||||
buf[0] = 0x40 | (ip4HeaderLength >> 2) // IPv4
|
||||
buf[1] = 0x00 // DHCP, ECN
|
||||
put16(buf[2:4], uint16(len(buf)))
|
||||
put16(buf[4:6], h.IPID)
|
||||
put16(buf[6:8], 0) // flags, offset
|
||||
buf[8] = 64 // TTL
|
||||
binary.BigEndian.PutUint16(buf[2:4], uint16(len(buf)))
|
||||
binary.BigEndian.PutUint16(buf[4:6], h.IPID)
|
||||
binary.BigEndian.PutUint16(buf[6:8], 0) // flags, offset
|
||||
buf[8] = 64 // TTL
|
||||
buf[9] = uint8(h.IPProto)
|
||||
put16(buf[10:12], 0) // blank IP header checksum
|
||||
put32(buf[12:16], uint32(h.SrcIP))
|
||||
put32(buf[16:20], uint32(h.DstIP))
|
||||
binary.BigEndian.PutUint16(buf[10:12], 0) // blank IP header checksum
|
||||
binary.BigEndian.PutUint32(buf[12:16], uint32(h.SrcIP))
|
||||
binary.BigEndian.PutUint32(buf[16:20], uint32(h.DstIP))
|
||||
|
||||
put16(buf[10:12], ipChecksum(buf[0:20]))
|
||||
binary.BigEndian.PutUint16(buf[10:12], ipChecksum(buf[0:20]))
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -97,11 +98,11 @@ func (h IP4Header) MarshalPseudo(buf []byte) error {
|
||||
}
|
||||
|
||||
length := len(buf) - ip4HeaderLength
|
||||
put32(buf[8:12], uint32(h.SrcIP))
|
||||
put32(buf[12:16], uint32(h.DstIP))
|
||||
binary.BigEndian.PutUint32(buf[8:12], uint32(h.SrcIP))
|
||||
binary.BigEndian.PutUint32(buf[12:16], uint32(h.DstIP))
|
||||
buf[16] = 0x0
|
||||
buf[17] = uint8(h.IPProto)
|
||||
put16(buf[18:20], uint16(length))
|
||||
binary.BigEndian.PutUint16(buf[18:20], uint16(length))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -21,14 +21,6 @@ const (
|
||||
TCPSynAck = TCPSyn | TCPAck
|
||||
)
|
||||
|
||||
var (
|
||||
get16 = binary.BigEndian.Uint16
|
||||
get32 = binary.BigEndian.Uint32
|
||||
|
||||
put16 = binary.BigEndian.PutUint16
|
||||
put32 = binary.BigEndian.PutUint32
|
||||
)
|
||||
|
||||
// Parsed is a minimal decoding of a packet suitable for use in filters.
|
||||
//
|
||||
// In general, it only supports IPv4. The IPv6 parsing is very minimal.
|
||||
@ -114,7 +106,7 @@ func ipChecksum(b []byte) uint16 {
|
||||
i := 0
|
||||
n := len(b)
|
||||
for n >= 2 {
|
||||
ac += uint32(get16(b[i : i+2]))
|
||||
ac += uint32(binary.BigEndian.Uint16(b[i : i+2]))
|
||||
n -= 2
|
||||
i += 2
|
||||
}
|
||||
@ -161,7 +153,7 @@ func (q *Parsed) decode4(b []byte) {
|
||||
|
||||
// Check that it's IPv4.
|
||||
q.IPProto = IPProto(b[9])
|
||||
q.length = int(get16(b[2:4]))
|
||||
q.length = int(binary.BigEndian.Uint16(b[2:4]))
|
||||
if len(b) < q.length {
|
||||
// Packet was cut off before full IPv4 length.
|
||||
q.IPProto = Unknown
|
||||
@ -169,8 +161,8 @@ func (q *Parsed) decode4(b []byte) {
|
||||
}
|
||||
|
||||
// If it's valid IPv4, then the IP addresses are valid
|
||||
q.SrcIP4 = IP4(get32(b[12:16]))
|
||||
q.DstIP4 = IP4(get32(b[16:20]))
|
||||
q.SrcIP4 = IP4(binary.BigEndian.Uint32(b[12:16]))
|
||||
q.DstIP4 = IP4(binary.BigEndian.Uint32(b[16:20]))
|
||||
|
||||
q.subofs = int((b[0] & 0x0F) << 2)
|
||||
sub := b[q.subofs:]
|
||||
@ -187,7 +179,7 @@ func (q *Parsed) decode4(b []byte) {
|
||||
// zero reason to send such a short first fragment, so we can treat
|
||||
// it as Unknown. We can also treat any subsequent fragment that starts
|
||||
// at such a low offset as Unknown.
|
||||
fragFlags := get16(b[6:8])
|
||||
fragFlags := binary.BigEndian.Uint16(b[6:8])
|
||||
moreFrags := (fragFlags & 0x20) != 0
|
||||
fragOfs := fragFlags & 0x1FFF
|
||||
if fragOfs == 0 {
|
||||
@ -215,8 +207,8 @@ func (q *Parsed) decode4(b []byte) {
|
||||
q.IPProto = Unknown
|
||||
return
|
||||
}
|
||||
q.SrcPort = get16(sub[0:2])
|
||||
q.DstPort = get16(sub[2:4])
|
||||
q.SrcPort = binary.BigEndian.Uint16(sub[0:2])
|
||||
q.DstPort = binary.BigEndian.Uint16(sub[2:4])
|
||||
q.TCPFlags = sub[13] & 0x3F
|
||||
headerLength := (sub[12] & 0xF0) >> 2
|
||||
q.dataofs = q.subofs + int(headerLength)
|
||||
@ -226,8 +218,8 @@ func (q *Parsed) decode4(b []byte) {
|
||||
q.IPProto = Unknown
|
||||
return
|
||||
}
|
||||
q.SrcPort = get16(sub[0:2])
|
||||
q.DstPort = get16(sub[2:4])
|
||||
q.SrcPort = binary.BigEndian.Uint16(sub[0:2])
|
||||
q.DstPort = binary.BigEndian.Uint16(sub[2:4])
|
||||
q.dataofs = q.subofs + udpHeaderLength
|
||||
return
|
||||
default:
|
||||
@ -261,7 +253,7 @@ func (q *Parsed) decode6(b []byte) {
|
||||
}
|
||||
|
||||
q.IPProto = IPProto(b[6])
|
||||
q.length = int(get16(b[4:6])) + ip6HeaderLength
|
||||
q.length = int(binary.BigEndian.Uint16(b[4:6])) + ip6HeaderLength
|
||||
if len(b) < q.length {
|
||||
// Packet was cut off before the full IPv6 length.
|
||||
q.IPProto = Unknown
|
||||
@ -300,8 +292,8 @@ func (q *Parsed) decode6(b []byte) {
|
||||
q.IPProto = Unknown
|
||||
return
|
||||
}
|
||||
q.SrcPort = get16(sub[0:2])
|
||||
q.DstPort = get16(sub[2:4])
|
||||
q.SrcPort = binary.BigEndian.Uint16(sub[0:2])
|
||||
q.DstPort = binary.BigEndian.Uint16(sub[2:4])
|
||||
q.TCPFlags = sub[13] & 0x3F
|
||||
headerLength := (sub[12] & 0xF0) >> 2
|
||||
q.dataofs = q.subofs + int(headerLength)
|
||||
@ -311,8 +303,8 @@ func (q *Parsed) decode6(b []byte) {
|
||||
q.IPProto = Unknown
|
||||
return
|
||||
}
|
||||
q.SrcPort = get16(sub[0:2])
|
||||
q.DstPort = get16(sub[2:4])
|
||||
q.SrcPort = binary.BigEndian.Uint16(sub[0:2])
|
||||
q.DstPort = binary.BigEndian.Uint16(sub[2:4])
|
||||
q.dataofs = q.subofs + udpHeaderLength
|
||||
default:
|
||||
q.IPProto = Unknown
|
||||
@ -324,7 +316,7 @@ func (q *Parsed) IP4Header() IP4Header {
|
||||
if q.IPVersion != 4 {
|
||||
panic("IP4Header called on non-IPv4 Parsed")
|
||||
}
|
||||
ipid := get16(q.b[4:6])
|
||||
ipid := binary.BigEndian.Uint16(q.b[4:6])
|
||||
return IP4Header{
|
||||
IPID: ipid,
|
||||
IPProto: q.IPProto,
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package packet
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
// UDPHeader represents an UDP packet header.
|
||||
type UDP4Header struct {
|
||||
IP4Header
|
||||
@ -32,15 +34,15 @@ func (h UDP4Header) Marshal(buf []byte) error {
|
||||
h.IPProto = UDP
|
||||
|
||||
length := len(buf) - h.IP4Header.Len()
|
||||
put16(buf[20:22], h.SrcPort)
|
||||
put16(buf[22:24], h.DstPort)
|
||||
put16(buf[24:26], uint16(length))
|
||||
put16(buf[26:28], 0) // blank checksum
|
||||
binary.BigEndian.PutUint16(buf[20:22], h.SrcPort)
|
||||
binary.BigEndian.PutUint16(buf[22:24], h.DstPort)
|
||||
binary.BigEndian.PutUint16(buf[24:26], uint16(length))
|
||||
binary.BigEndian.PutUint16(buf[26:28], 0) // blank checksum
|
||||
|
||||
h.IP4Header.MarshalPseudo(buf)
|
||||
|
||||
// UDP checksum with IP pseudo header.
|
||||
put16(buf[26:28], ipChecksum(buf[8:]))
|
||||
binary.BigEndian.PutUint16(buf[26:28], ipChecksum(buf[8:]))
|
||||
|
||||
h.IP4Header.Marshal(buf)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user