mirror of
https://github.com/slackhq/nebula.git
synced 2026-05-16 04:47:38 +02:00
SPICY
This commit is contained in:
@@ -23,7 +23,7 @@ func newFixedTicker(t *testing.T, l *slog.Logger, cacheLen int) *ConntrackCacheT
|
|||||||
cache: make(ConntrackCache, cacheLen),
|
cache: make(ConntrackCache, cacheLen),
|
||||||
}
|
}
|
||||||
for i := 0; i < cacheLen; i++ {
|
for i := 0; i < cacheLen; i++ {
|
||||||
c.cache[PacketKey{TransportTuple: TransportTuple{LocalPort: uint16(i) + 1}}] = struct{}{}
|
c.cache[PacketKey{LocalPort: uint16(i) + 1}] = struct{}{}
|
||||||
}
|
}
|
||||||
c.cacheTick.Store(1) // cacheV starts at 0, so Get() takes the reset path
|
c.cacheTick.Store(1) // cacheV starts at 0, so Get() takes the reset path
|
||||||
return c
|
return c
|
||||||
|
|||||||
@@ -19,19 +19,6 @@ const (
|
|||||||
PortFragment = -1 // Special value for matching `port: fragment`
|
PortFragment = -1 // Special value for matching `port: fragment`
|
||||||
)
|
)
|
||||||
|
|
||||||
// TransportTuple is the dense 5-tuple shape shared between the coalescer's
|
|
||||||
// flowKey-equivalent and the firewall's PacketKey. Stored in Local/Remote
|
|
||||||
// orientation so a flow's incoming and outgoing packets share the same
|
|
||||||
// tuple identity. v4 addresses occupy the low 4 bytes of LocalAddr/
|
|
||||||
// RemoteAddr (NOT v4-mapped form) so v4 vs v6 tuples never collide.
|
|
||||||
type TransportTuple struct {
|
|
||||||
LocalAddr [16]byte
|
|
||||||
RemoteAddr [16]byte
|
|
||||||
LocalPort uint16
|
|
||||||
RemotePort uint16
|
|
||||||
IsV6 bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// PacketKey is the firewall's conntrack and ConntrackCache map key — the
|
// PacketKey is the firewall's conntrack and ConntrackCache map key — the
|
||||||
// dense form of the 5-tuple plus the protocol and fragment flag the
|
// dense form of the 5-tuple plus the protocol and fragment flag the
|
||||||
// firewall actually discriminates flows on. Kept separate from Packet so
|
// firewall actually discriminates flows on. Kept separate from Packet so
|
||||||
@@ -42,9 +29,13 @@ type TransportTuple struct {
|
|||||||
// Superset of the coalescer's flowKey shape (same 5-tuple, just in
|
// Superset of the coalescer's flowKey shape (same 5-tuple, just in
|
||||||
// Local/Remote orientation rather than wire src/dst).
|
// Local/Remote orientation rather than wire src/dst).
|
||||||
type PacketKey struct {
|
type PacketKey struct {
|
||||||
TransportTuple
|
LocalAddr [16]byte
|
||||||
Protocol uint8
|
RemoteAddr [16]byte
|
||||||
Fragment bool
|
LocalPort uint16
|
||||||
|
RemotePort uint16
|
||||||
|
IsV6 bool
|
||||||
|
Protocol uint8
|
||||||
|
Fragment bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Packet struct {
|
type Packet struct {
|
||||||
@@ -104,6 +95,16 @@ func (k *PacketKey) Hydrate(fp *Packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k *PacketKey) GetRemoteAddr() netip.Addr {
|
||||||
|
if k.IsV6 {
|
||||||
|
return netip.AddrFrom16(k.RemoteAddr)
|
||||||
|
} else {
|
||||||
|
var v4 [4]byte
|
||||||
|
copy(v4[:], k.RemoteAddr[:4])
|
||||||
|
return netip.AddrFrom4(v4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (fp *Packet) Copy() *Packet {
|
func (fp *Packet) Copy() *Packet {
|
||||||
return &Packet{
|
return &Packet{
|
||||||
LocalAddr: fp.LocalAddr,
|
LocalAddr: fp.LocalAddr,
|
||||||
|
|||||||
13
inside.go
13
inside.go
@@ -28,7 +28,7 @@ func (f *Interface) consumeInsidePacket(pkt tio.Packet, fwPacket *firewall.Packe
|
|||||||
// the same 5-tuple every segment will share, so a single newPacket /
|
// the same 5-tuple every segment will share, so a single newPacket /
|
||||||
// firewall check covers the whole superpacket.
|
// firewall check covers the whole superpacket.
|
||||||
packet := pkt.Bytes
|
packet := pkt.Bytes
|
||||||
err := newPacket(packet, false, fwPacket)
|
key, err := newPacketKey(packet, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
||||||
f.l.Debug("Error while validating outbound packet",
|
f.l.Debug("Error while validating outbound packet",
|
||||||
@@ -39,6 +39,8 @@ func (f *Interface) consumeInsidePacket(pkt tio.Packet, fwPacket *firewall.Packe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key.Hydrate(fwPacket)
|
||||||
|
|
||||||
// Ignore local broadcast packets
|
// Ignore local broadcast packets
|
||||||
if f.dropLocalBroadcast {
|
if f.dropLocalBroadcast {
|
||||||
if f.myBroadcastAddrsTable.Contains(fwPacket.RemoteAddr) {
|
if f.myBroadcastAddrsTable.Contains(fwPacket.RemoteAddr) {
|
||||||
@@ -105,7 +107,7 @@ func (f *Interface) consumeInsidePacket(pkt tio.Packet, fwPacket *firewall.Packe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dropReason := f.firewall.Drop(fwPacket.Key(), fwPacket, false, hostinfo, f.pki.GetCAPool(), localCache)
|
dropReason := f.firewall.Drop(key, fwPacket, false, hostinfo, f.pki.GetCAPool(), localCache)
|
||||||
if dropReason == nil {
|
if dropReason == nil {
|
||||||
f.sendInsideMessage(hostinfo, pkt, nb, sendBatch, rejectBuf, q)
|
f.sendInsideMessage(hostinfo, pkt, nb, sendBatch, rejectBuf, q)
|
||||||
} else {
|
} else {
|
||||||
@@ -392,15 +394,16 @@ func (f *Interface) getOrHandshakeConsiderRouting(fwPacket *firewall.Packet, cac
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Interface) sendMessageNow(t header.MessageType, st header.MessageSubType, hostinfo *HostInfo, p, nb, out []byte) {
|
func (f *Interface) sendMessageNow(t header.MessageType, st header.MessageSubType, hostinfo *HostInfo, p, nb, out []byte) {
|
||||||
fp := &firewall.Packet{}
|
key, err := newPacketKey(p, false)
|
||||||
err := newPacket(p, false, fp)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.l.Warn("error while parsing outgoing packet for firewall check", "error", err)
|
f.l.Warn("error while parsing outgoing packet for firewall check", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
fp := &firewall.Packet{}
|
||||||
|
key.Hydrate(fp)
|
||||||
|
|
||||||
// check if packet is in outbound fw rules
|
// check if packet is in outbound fw rules
|
||||||
dropReason := f.firewall.Drop(fp.Key(), fp, false, hostinfo, f.pki.GetCAPool(), nil)
|
dropReason := f.firewall.Drop(key, fp, false, hostinfo, f.pki.GetCAPool(), nil)
|
||||||
if dropReason != nil {
|
if dropReason != nil {
|
||||||
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
if f.l.Enabled(context.Background(), slog.LevelDebug) {
|
||||||
f.l.Debug("dropping cached packet",
|
f.l.Debug("dropping cached packet",
|
||||||
|
|||||||
169
outside.go
169
outside.go
@@ -313,37 +313,54 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// newPacket validates and parses the interesting bits for the firewall out of the ip and sub protocol headers
|
// newPacket validates and parses the interesting bits for the firewall out of the ip and sub protocol headers
|
||||||
|
// newPacket parses data into a fully-hydrated firewall.Packet — kept as a
|
||||||
|
// thin wrapper around newPacketKey + Hydrate so there's one source of
|
||||||
|
// parse logic. Callers that don't need the netip.Addr-rich form (e.g.
|
||||||
|
// conntrack-only paths) should use newPacketKey directly.
|
||||||
func newPacket(data []byte, incoming bool, fp *firewall.Packet) error {
|
func newPacket(data []byte, incoming bool, fp *firewall.Packet) error {
|
||||||
if len(data) < 1 {
|
key, err := newPacketKey(data, incoming)
|
||||||
return ErrPacketTooShort
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
key.Hydrate(fp)
|
||||||
version := int((data[0] >> 4) & 0x0f)
|
return nil
|
||||||
switch version {
|
|
||||||
case ipv4.Version:
|
|
||||||
return parseV4(data, incoming, fp)
|
|
||||||
case ipv6.Version:
|
|
||||||
return parseV6(data, incoming, fp)
|
|
||||||
}
|
|
||||||
return ErrUnknownIPVersion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseV6(data []byte, incoming bool, fp *firewall.Packet) error {
|
// newPacketKey parses data into a dense firewall.PacketKey. Hot path: no
|
||||||
|
// netip.Addr construction, no unique.Handle interning. Caller decides
|
||||||
|
// whether to also Hydrate to a Packet (for rule matching) or pass the key
|
||||||
|
// straight to conntrack.
|
||||||
|
func newPacketKey(data []byte, incoming bool) (firewall.PacketKey, error) {
|
||||||
|
var k firewall.PacketKey
|
||||||
|
if len(data) < 1 {
|
||||||
|
return k, ErrPacketTooShort
|
||||||
|
}
|
||||||
|
switch int((data[0] >> 4) & 0x0f) {
|
||||||
|
case ipv4.Version:
|
||||||
|
return k, parseV4Key(data, incoming, &k)
|
||||||
|
case ipv6.Version:
|
||||||
|
k.IsV6 = true
|
||||||
|
return k, parseV6Key(data, incoming, &k)
|
||||||
|
}
|
||||||
|
return k, ErrUnknownIPVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseV6Key(data []byte, incoming bool, k *firewall.PacketKey) error {
|
||||||
dataLen := len(data)
|
dataLen := len(data)
|
||||||
if dataLen < ipv6.HeaderLen {
|
if dataLen < ipv6.HeaderLen {
|
||||||
return ErrIPv6PacketTooShort
|
return ErrIPv6PacketTooShort
|
||||||
}
|
}
|
||||||
|
|
||||||
if incoming {
|
if incoming {
|
||||||
fp.RemoteAddr, _ = netip.AddrFromSlice(data[8:24])
|
copy(k.RemoteAddr[:], data[8:24])
|
||||||
fp.LocalAddr, _ = netip.AddrFromSlice(data[24:40])
|
copy(k.LocalAddr[:], data[24:40])
|
||||||
} else {
|
} else {
|
||||||
fp.LocalAddr, _ = netip.AddrFromSlice(data[8:24])
|
copy(k.LocalAddr[:], data[8:24])
|
||||||
fp.RemoteAddr, _ = netip.AddrFromSlice(data[24:40])
|
copy(k.RemoteAddr[:], data[24:40])
|
||||||
}
|
}
|
||||||
|
|
||||||
protoAt := 6 // NextHeader is at 6 bytes into the ipv6 header
|
protoAt := 6
|
||||||
offset := ipv6.HeaderLen // Start at the end of the ipv6 header
|
offset := ipv6.HeaderLen
|
||||||
next := 0
|
next := 0
|
||||||
for {
|
for {
|
||||||
if protoAt >= dataLen {
|
if protoAt >= dataLen {
|
||||||
@@ -353,87 +370,72 @@ func parseV6(data []byte, incoming bool, fp *firewall.Packet) error {
|
|||||||
|
|
||||||
switch proto {
|
switch proto {
|
||||||
case layers.IPProtocolESP, layers.IPProtocolNoNextHeader:
|
case layers.IPProtocolESP, layers.IPProtocolNoNextHeader:
|
||||||
fp.Protocol = uint8(proto)
|
k.Protocol = uint8(proto)
|
||||||
fp.RemotePort = 0
|
k.RemotePort = 0
|
||||||
fp.LocalPort = 0
|
k.LocalPort = 0
|
||||||
fp.Fragment = false
|
k.Fragment = false
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case layers.IPProtocolICMPv6:
|
case layers.IPProtocolICMPv6:
|
||||||
if dataLen < offset+6 {
|
if dataLen < offset+6 {
|
||||||
return ErrIPv6PacketTooShort
|
return ErrIPv6PacketTooShort
|
||||||
}
|
}
|
||||||
fp.Protocol = uint8(proto)
|
k.Protocol = uint8(proto)
|
||||||
fp.LocalPort = 0 //incoming vs outgoing doesn't matter for icmpv6
|
k.LocalPort = 0
|
||||||
icmptype := data[offset+1]
|
switch data[offset+1] {
|
||||||
switch icmptype {
|
|
||||||
case layers.ICMPv6TypeEchoRequest, layers.ICMPv6TypeEchoReply:
|
case layers.ICMPv6TypeEchoRequest, layers.ICMPv6TypeEchoReply:
|
||||||
fp.RemotePort = binary.BigEndian.Uint16(data[offset+4 : offset+6]) //identifier
|
k.RemotePort = binary.BigEndian.Uint16(data[offset+4 : offset+6])
|
||||||
default:
|
default:
|
||||||
fp.RemotePort = 0
|
k.RemotePort = 0
|
||||||
}
|
}
|
||||||
fp.Fragment = false
|
k.Fragment = false
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case layers.IPProtocolTCP, layers.IPProtocolUDP:
|
case layers.IPProtocolTCP, layers.IPProtocolUDP:
|
||||||
if dataLen < offset+4 {
|
if dataLen < offset+4 {
|
||||||
return ErrIPv6PacketTooShort
|
return ErrIPv6PacketTooShort
|
||||||
}
|
}
|
||||||
|
k.Protocol = uint8(proto)
|
||||||
fp.Protocol = uint8(proto)
|
|
||||||
if incoming {
|
if incoming {
|
||||||
fp.RemotePort = binary.BigEndian.Uint16(data[offset : offset+2])
|
k.RemotePort = binary.BigEndian.Uint16(data[offset : offset+2])
|
||||||
fp.LocalPort = binary.BigEndian.Uint16(data[offset+2 : offset+4])
|
k.LocalPort = binary.BigEndian.Uint16(data[offset+2 : offset+4])
|
||||||
} else {
|
} else {
|
||||||
fp.LocalPort = binary.BigEndian.Uint16(data[offset : offset+2])
|
k.LocalPort = binary.BigEndian.Uint16(data[offset : offset+2])
|
||||||
fp.RemotePort = binary.BigEndian.Uint16(data[offset+2 : offset+4])
|
k.RemotePort = binary.BigEndian.Uint16(data[offset+2 : offset+4])
|
||||||
}
|
}
|
||||||
|
k.Fragment = false
|
||||||
fp.Fragment = false
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case layers.IPProtocolIPv6Fragment:
|
case layers.IPProtocolIPv6Fragment:
|
||||||
// Fragment header is 8 bytes, need at least offset+4 to read the offset field
|
|
||||||
if dataLen < offset+8 {
|
if dataLen < offset+8 {
|
||||||
return ErrIPv6PacketTooShort
|
return ErrIPv6PacketTooShort
|
||||||
}
|
}
|
||||||
|
fragmentOffset := binary.BigEndian.Uint16(data[offset+2:offset+4]) &^ uint16(0x7)
|
||||||
// Check if this is the first fragment
|
|
||||||
fragmentOffset := binary.BigEndian.Uint16(data[offset+2:offset+4]) &^ uint16(0x7) // Remove the reserved and M flag bits
|
|
||||||
if fragmentOffset != 0 {
|
if fragmentOffset != 0 {
|
||||||
// Non-first fragment, use what we have now and stop processing
|
k.Protocol = data[offset]
|
||||||
fp.Protocol = data[offset]
|
k.Fragment = true
|
||||||
fp.Fragment = true
|
k.RemotePort = 0
|
||||||
fp.RemotePort = 0
|
k.LocalPort = 0
|
||||||
fp.LocalPort = 0
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
next = 8
|
||||||
// The next loop should be the transport layer since we are the first fragment
|
|
||||||
next = 8 // Fragment headers are always 8 bytes
|
|
||||||
|
|
||||||
case layers.IPProtocolAH:
|
case layers.IPProtocolAH:
|
||||||
// Auth headers, used by IPSec, have a different meaning for header length
|
|
||||||
if dataLen <= offset+1 {
|
if dataLen <= offset+1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
next = int(data[offset+1]+2) << 2
|
next = int(data[offset+1]+2) << 2
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Normal ipv6 header length processing
|
|
||||||
if dataLen <= offset+1 {
|
if dataLen <= offset+1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
next = int(data[offset+1]+1) << 3
|
next = int(data[offset+1]+1) << 3
|
||||||
}
|
}
|
||||||
|
|
||||||
if next <= 0 {
|
if next <= 0 {
|
||||||
// Safety check, each ipv6 header has to be at least 8 bytes
|
|
||||||
next = 8
|
next = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
protoAt = offset
|
protoAt = offset
|
||||||
offset = offset + next
|
offset = offset + next
|
||||||
}
|
}
|
||||||
@@ -441,61 +443,54 @@ func parseV6(data []byte, incoming bool, fp *firewall.Packet) error {
|
|||||||
return ErrIPv6CouldNotFindPayload
|
return ErrIPv6CouldNotFindPayload
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseV4(data []byte, incoming bool, fp *firewall.Packet) error {
|
func parseV4Key(data []byte, incoming bool, k *firewall.PacketKey) error {
|
||||||
// Do we at least have an ipv4 header worth of data?
|
|
||||||
if len(data) < ipv4.HeaderLen {
|
if len(data) < ipv4.HeaderLen {
|
||||||
return ErrIPv4PacketTooShort
|
return ErrIPv4PacketTooShort
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust our start position based on the advertised ip header length
|
|
||||||
ihl := int(data[0]&0x0f) << 2
|
ihl := int(data[0]&0x0f) << 2
|
||||||
|
|
||||||
// Well-formed ip header length?
|
|
||||||
if ihl < ipv4.HeaderLen {
|
if ihl < ipv4.HeaderLen {
|
||||||
return ErrIPv4InvalidHeaderLength
|
return ErrIPv4InvalidHeaderLength
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is the second or further fragment of a fragmented packet.
|
|
||||||
flagsfrags := binary.BigEndian.Uint16(data[6:8])
|
flagsfrags := binary.BigEndian.Uint16(data[6:8])
|
||||||
fp.Fragment = (flagsfrags & 0x1FFF) != 0
|
k.Fragment = (flagsfrags & 0x1FFF) != 0
|
||||||
|
k.Protocol = data[9]
|
||||||
|
|
||||||
// Firewall handles protocol checks
|
|
||||||
fp.Protocol = data[9]
|
|
||||||
|
|
||||||
// Accounting for a variable header length, do we have enough data for our src/dst tuples?
|
|
||||||
minLen := ihl
|
minLen := ihl
|
||||||
if !fp.Fragment {
|
if !k.Fragment {
|
||||||
if fp.Protocol == firewall.ProtoICMP {
|
if k.Protocol == firewall.ProtoICMP {
|
||||||
minLen += minFwPacketLen + 2
|
minLen += minFwPacketLen + 2
|
||||||
} else {
|
} else {
|
||||||
minLen += minFwPacketLen
|
minLen += minFwPacketLen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(data) < minLen {
|
if len(data) < minLen {
|
||||||
return ErrIPv4InvalidHeaderLength
|
return ErrIPv4InvalidHeaderLength
|
||||||
}
|
}
|
||||||
|
|
||||||
if incoming { // Firewall packets are locally oriented
|
// Dense form: v4 in low 4 bytes, rest zero. Matches the coalescer's
|
||||||
fp.RemoteAddr, _ = netip.AddrFromSlice(data[12:16])
|
// flowKey convention so the two stay byte-identical for the same flow.
|
||||||
fp.LocalAddr, _ = netip.AddrFromSlice(data[16:20])
|
if incoming {
|
||||||
|
copy(k.RemoteAddr[:4], data[12:16])
|
||||||
|
copy(k.LocalAddr[:4], data[16:20])
|
||||||
} else {
|
} else {
|
||||||
fp.LocalAddr, _ = netip.AddrFromSlice(data[12:16])
|
copy(k.LocalAddr[:4], data[12:16])
|
||||||
fp.RemoteAddr, _ = netip.AddrFromSlice(data[16:20])
|
copy(k.RemoteAddr[:4], data[16:20])
|
||||||
}
|
}
|
||||||
|
|
||||||
if fp.Fragment {
|
switch {
|
||||||
fp.RemotePort = 0
|
case k.Fragment:
|
||||||
fp.LocalPort = 0
|
k.RemotePort = 0
|
||||||
} else if fp.Protocol == firewall.ProtoICMP { //note that orientation doesn't matter on ICMP
|
k.LocalPort = 0
|
||||||
fp.RemotePort = binary.BigEndian.Uint16(data[ihl+4 : ihl+6]) //identifier
|
case k.Protocol == firewall.ProtoICMP:
|
||||||
fp.LocalPort = 0 //code would be uint16(data[ihl+1])
|
k.RemotePort = binary.BigEndian.Uint16(data[ihl+4 : ihl+6])
|
||||||
} else if incoming {
|
k.LocalPort = 0
|
||||||
fp.RemotePort = binary.BigEndian.Uint16(data[ihl : ihl+2]) //src port
|
case incoming:
|
||||||
fp.LocalPort = binary.BigEndian.Uint16(data[ihl+2 : ihl+4]) //dst port
|
k.RemotePort = binary.BigEndian.Uint16(data[ihl : ihl+2])
|
||||||
} else {
|
k.LocalPort = binary.BigEndian.Uint16(data[ihl+2 : ihl+4])
|
||||||
fp.LocalPort = binary.BigEndian.Uint16(data[ihl : ihl+2]) //src port
|
default:
|
||||||
fp.RemotePort = binary.BigEndian.Uint16(data[ihl+2 : ihl+4]) //dst port
|
k.LocalPort = binary.BigEndian.Uint16(data[ihl : ihl+2])
|
||||||
|
k.RemotePort = binary.BigEndian.Uint16(data[ihl+2 : ihl+4])
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -529,7 +529,7 @@ func BenchmarkParseV6(b *testing.B) {
|
|||||||
|
|
||||||
b.Run("Normal", func(b *testing.B) {
|
b.Run("Normal", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if err = parseV6(normalPacket, true, fp); err != nil {
|
if err = newPacket(normalPacket, true, fp); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -537,7 +537,7 @@ func BenchmarkParseV6(b *testing.B) {
|
|||||||
|
|
||||||
b.Run("FirstFragment", func(b *testing.B) {
|
b.Run("FirstFragment", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if err = parseV6(firstFrag, true, fp); err != nil {
|
if err = newPacket(firstFrag, true, fp); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -545,7 +545,7 @@ func BenchmarkParseV6(b *testing.B) {
|
|||||||
|
|
||||||
b.Run("SecondFragment", func(b *testing.B) {
|
b.Run("SecondFragment", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if err = parseV6(secondFrag, true, fp); err != nil {
|
if err = newPacket(secondFrag, true, fp); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -590,7 +590,7 @@ func BenchmarkParseV6(b *testing.B) {
|
|||||||
|
|
||||||
b.Run("200 HopByHop headers", func(b *testing.B) {
|
b.Run("200 HopByHop headers", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
if err = parseV6(evilBytes, false, fp); err != nil {
|
if err = newPacket(evilBytes, false, fp); err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user