github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/nfqdatapath/nflog/nflog_linux.go (about) 1 // +build linux 2 3 package nflog 4 5 import ( 6 "context" 7 "sync" 8 "time" 9 10 "go.aporeto.io/enforcerd/trireme-lib/collector" 11 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/counters" 12 "go.aporeto.io/enforcerd/trireme-lib/utils/cache" 13 "go.aporeto.io/netlink-go/nflog" 14 "go.uber.org/zap" 15 ) 16 17 type nfLog struct { 18 getPUContext GetPUContextFunc 19 ipv4groupSource uint16 20 ipv4groupDest uint16 21 collector collector.EventCollector 22 srcNflogHandle nflog.NFLog 23 dstNflogHandle nflog.NFLog 24 flowReportCache cache.DataStore 25 sync.Mutex 26 } 27 28 // NewNFLogger provides an NFLog instance 29 func NewNFLogger(ipv4groupSource, ipv4groupDest uint16, getPUContext GetPUContextFunc, collector collector.EventCollector) NFLogger { 30 nfLog := &nfLog{ 31 ipv4groupSource: ipv4groupSource, 32 ipv4groupDest: ipv4groupDest, 33 collector: collector, 34 getPUContext: getPUContext, 35 } 36 nfLog.flowReportCache = cache.NewCacheWithExpirationNotifier("flowReportCache", time.Second*5, nfLog.logExpirationNotifier) 37 return nfLog 38 } 39 40 // Run runs the Nf Logger 41 func (a *nfLog) Run(ctx context.Context) { 42 a.Lock() 43 a.srcNflogHandle, _ = nflog.BindAndListenForLogs([]uint16{a.ipv4groupSource}, 64, a.sourceNFLogsHanlder, a.nflogErrorHandler) 44 a.dstNflogHandle, _ = nflog.BindAndListenForLogs([]uint16{a.ipv4groupDest}, 64, a.destNFLogsHandler, a.nflogErrorHandler) 45 a.Unlock() 46 47 go func() { 48 <-ctx.Done() 49 a.Lock() 50 a.srcNflogHandle.NFlogClose() 51 a.dstNflogHandle.NFlogClose() 52 a.Unlock() 53 54 }() 55 } 56 57 func (a *nfLog) sourceNFLogsHanlder(buf *nflog.NfPacket, _ interface{}) { 58 59 record, packetEvent, err := a.recordFromNFLogBuffer(buf, false) 60 if err != nil { 61 zap.L().Error("sourceNFLogsHanlder: create flow record", zap.Error(err)) 62 return 63 } 64 65 handleFlowReport(a.flowReportCache, a.collector, record, false) 66 67 if packetEvent != nil { 68 a.collector.CollectPacketEvent(packetEvent) 69 } 70 } 71 72 func (a *nfLog) destNFLogsHandler(buf *nflog.NfPacket, _ interface{}) { 73 74 record, packetEvent, err := a.recordFromNFLogBuffer(buf, true) 75 if err != nil { 76 zap.L().Error("destNFLogsHandler: create flow record", zap.Error(err)) 77 return 78 } 79 80 handleFlowReport(a.flowReportCache, a.collector, record, true) 81 82 if packetEvent != nil { 83 a.collector.CollectPacketEvent(packetEvent) 84 } 85 } 86 87 func (a *nfLog) nflogErrorHandler(err error) { 88 counters.IncrementCounter(counters.ErrNfLogError) 89 zap.L().Debug("Error while processing nflog packet", zap.Error(err)) 90 } 91 92 func (a *nfLog) recordFromNFLogBuffer(buf *nflog.NfPacket, puIsSource bool) (*collector.FlowRecord, *collector.PacketReport, error) { 93 return recordFromNFLogData(buf.Payload, buf.Prefix, buf.Protocol, buf.SrcIP, buf.DstIP, buf.SrcPort, buf.DstPort, a.getPUContext, puIsSource) 94 } 95 96 func (a *nfLog) logExpirationNotifier(_ interface{}, item interface{}) { 97 if item != nil { 98 // Basically we had an observed flow report that didn't get reported yet. 99 record := item.(*collector.FlowRecord) 100 a.collector.CollectFlowEvent(record) 101 } 102 }