cache.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package firewall
  2. import (
  3. "context"
  4. "sync/atomic"
  5. "time"
  6. "github.com/sirupsen/logrus"
  7. )
  8. // ConntrackCache is used as a local routine cache to know if a given flow
  9. // has been seen in the conntrack table.
  10. type ConntrackCache map[Packet]struct{}
  11. type ConntrackCacheTicker struct {
  12. cacheV uint64
  13. cacheTick atomic.Uint64
  14. cache ConntrackCache
  15. }
  16. func NewConntrackCacheTicker(ctx context.Context, d time.Duration) *ConntrackCacheTicker {
  17. if d == 0 {
  18. return nil
  19. }
  20. c := &ConntrackCacheTicker{
  21. cache: ConntrackCache{},
  22. }
  23. go c.tick(ctx, d)
  24. return c
  25. }
  26. func (c *ConntrackCacheTicker) tick(ctx context.Context, d time.Duration) {
  27. t := time.NewTicker(d)
  28. defer t.Stop()
  29. for {
  30. select {
  31. case <-ctx.Done():
  32. return
  33. case <-t.C:
  34. c.cacheTick.Add(1)
  35. }
  36. }
  37. }
  38. // Get checks if the cache ticker has moved to the next version before returning
  39. // the map. If it has moved, we reset the map.
  40. func (c *ConntrackCacheTicker) Get(l *logrus.Logger) ConntrackCache {
  41. if c == nil {
  42. return nil
  43. }
  44. if tick := c.cacheTick.Load(); tick != c.cacheV {
  45. c.cacheV = tick
  46. if ll := len(c.cache); ll > 0 {
  47. if l.Level == logrus.DebugLevel {
  48. l.WithField("len", ll).Debug("resetting conntrack cache")
  49. }
  50. c.cache = make(ConntrackCache, ll)
  51. }
  52. }
  53. return c.cache
  54. }