| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- package firewall
- import (
- "context"
- "log/slog"
- "sync/atomic"
- "time"
- "github.com/slackhq/nebula/logging"
- )
- // ConntrackCache is used as a local routine cache to know if a given flow
- // 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
- cacheTick atomic.Uint64
- l *slog.Logger
- cache ConntrackCache
- }
- func NewConntrackCacheTicker(ctx context.Context, l *slog.Logger, d time.Duration) *ConntrackCacheTicker {
- if d == 0 {
- return nil
- }
- c := &ConntrackCacheTicker{
- l: l,
- cache: ConntrackCache{},
- }
- go c.tick(ctx, d)
- return c
- }
- func (c *ConntrackCacheTicker) tick(ctx context.Context, d time.Duration) {
- t := time.NewTicker(d)
- defer t.Stop()
- for {
- select {
- case <-ctx.Done():
- return
- case <-t.C:
- c.cacheTick.Add(1)
- }
- }
- }
- // Get checks if the cache ticker has moved to the next version before returning
- // the map. If it has moved, we reset the map.
- func (c *ConntrackCacheTicker) Get() ConntrackCache {
- if c == nil {
- return nil
- }
- if tick := c.cacheTick.Load(); tick != c.cacheV {
- c.cacheV = tick
- if ll := len(c.cache); ll > 0 {
- if c.l.Enabled(context.Background(), logging.LevelTrace) {
- c.l.Log(context.Background(), logging.LevelTrace, "resetting conntrack cache", "len", ll)
- }
- c.cache = make(ConntrackCache, ll)
- }
- }
- return c.cache
- }
|