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  }