mirror of
https://github.com/slackhq/nebula.git
synced 2026-05-16 04:47:38 +02:00
checkpt, try to parse packets only once pt2
This commit is contained in:
@@ -10,8 +10,10 @@ import (
|
||||
)
|
||||
|
||||
// ConntrackCache is used as a local routine cache to know if a given flow
|
||||
// has been seen in the conntrack table.
|
||||
type ConntrackCache map[Packet]struct{}
|
||||
// has been seen in the conntrack table. Keyed on PacketKey (dense form)
|
||||
// rather than Packet so the lookup hashes raw bytes instead of the
|
||||
// unique.Handle each netip.Addr in Packet carries.
|
||||
type ConntrackCache map[PacketKey]struct{}
|
||||
|
||||
type ConntrackCacheTicker struct {
|
||||
cacheV uint64
|
||||
|
||||
@@ -23,7 +23,7 @@ func newFixedTicker(t *testing.T, l *slog.Logger, cacheLen int) *ConntrackCacheT
|
||||
cache: make(ConntrackCache, cacheLen),
|
||||
}
|
||||
for i := 0; i < cacheLen; i++ {
|
||||
c.cache[Packet{LocalPort: uint16(i) + 1}] = struct{}{}
|
||||
c.cache[PacketKey{TransportTuple: TransportTuple{LocalPort: uint16(i) + 1}}] = struct{}{}
|
||||
}
|
||||
c.cacheTick.Store(1) // cacheV starts at 0, so Get() takes the reset path
|
||||
return c
|
||||
|
||||
@@ -19,14 +19,34 @@ const (
|
||||
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 {
|
||||
FirstAddr [16]byte
|
||||
SecondAddr [16]byte
|
||||
FirstPort uint16
|
||||
SecondPort uint16
|
||||
LocalAddr [16]byte
|
||||
RemoteAddr [16]byte
|
||||
LocalPort uint16
|
||||
RemotePort uint16
|
||||
IsV6 bool
|
||||
}
|
||||
|
||||
// PacketKey is the firewall's conntrack and ConntrackCache map key — the
|
||||
// dense form of the 5-tuple plus the protocol and fragment flag the
|
||||
// firewall actually discriminates flows on. Kept separate from Packet so
|
||||
// the conntrack-hit fast path doesn't pay for hashing the unique.Handle
|
||||
// each netip.Addr carries, and so the inbound parser can skip the
|
||||
// AddrFrom4/AddrFrom16 calls until rule matching actually needs them.
|
||||
//
|
||||
// Superset of the coalescer's flowKey shape (same 5-tuple, just in
|
||||
// Local/Remote orientation rather than wire src/dst).
|
||||
type PacketKey struct {
|
||||
TransportTuple
|
||||
Protocol uint8
|
||||
Fragment bool
|
||||
}
|
||||
|
||||
type Packet struct {
|
||||
LocalAddr netip.Addr
|
||||
RemoteAddr netip.Addr
|
||||
@@ -39,6 +59,51 @@ type Packet struct {
|
||||
Fragment bool
|
||||
}
|
||||
|
||||
// Key derives a PacketKey from a populated Packet. Used by the outgoing
|
||||
// path (inside.go) which still parses into a full Packet via newPacket
|
||||
// before the firewall check; the inbound path skips this hop entirely by
|
||||
// having its parser write straight into the PacketKey.
|
||||
func (fp *Packet) Key() PacketKey {
|
||||
k := PacketKey{
|
||||
Protocol: fp.Protocol,
|
||||
Fragment: fp.Fragment,
|
||||
}
|
||||
k.LocalPort = fp.LocalPort
|
||||
k.RemotePort = fp.RemotePort
|
||||
k.IsV6 = !fp.LocalAddr.Is4()
|
||||
if k.IsV6 {
|
||||
k.LocalAddr = fp.LocalAddr.As16()
|
||||
k.RemoteAddr = fp.RemoteAddr.As16()
|
||||
} else {
|
||||
v4 := fp.LocalAddr.As4()
|
||||
copy(k.LocalAddr[:4], v4[:])
|
||||
v4 = fp.RemoteAddr.As4()
|
||||
copy(k.RemoteAddr[:4], v4[:])
|
||||
}
|
||||
return k
|
||||
}
|
||||
|
||||
// Hydrate fills fp's netip.Addr fields and copies the rest from k. Called
|
||||
// by the firewall slow path when conntrack misses and rule matching needs
|
||||
// the rich Packet form (CIDR lookups, family checks). The fast path skips
|
||||
// this entirely.
|
||||
func (k *PacketKey) Hydrate(fp *Packet) {
|
||||
fp.LocalPort = k.LocalPort
|
||||
fp.RemotePort = k.RemotePort
|
||||
fp.Protocol = k.Protocol
|
||||
fp.Fragment = k.Fragment
|
||||
if k.IsV6 {
|
||||
fp.LocalAddr = netip.AddrFrom16(k.LocalAddr)
|
||||
fp.RemoteAddr = netip.AddrFrom16(k.RemoteAddr)
|
||||
} else {
|
||||
var v4 [4]byte
|
||||
copy(v4[:], k.LocalAddr[:4])
|
||||
fp.LocalAddr = netip.AddrFrom4(v4)
|
||||
copy(v4[:], k.RemoteAddr[:4])
|
||||
fp.RemoteAddr = netip.AddrFrom4(v4)
|
||||
}
|
||||
}
|
||||
|
||||
func (fp *Packet) Copy() *Packet {
|
||||
return &Packet{
|
||||
LocalAddr: fp.LocalAddr,
|
||||
|
||||
Reference in New Issue
Block a user