Documentation ¶
Overview ¶
Package afring implements a capture.Source and a capture.SourceZeroCopy that allows reading network packets from Linux network interfaces via the AF_PACKET / TPacket ring buffer mechanism. This implementation relies on performing optimized `PPOLL()` syscalls to the MMAP'ed socket to fetch blocks of packets. The ring buffer is configurable (depending on the expected throughput). This capture method is optimally suited for production-level packet capture since it achieves blazing-fast capture rates (in particular in zero-copy mode).
Index ¶
- Constants
- Variables
- type MockSource
- func (m *MockSource) AddPacket(pkt capture.Packet) error
- func (m *MockSource) AddPacketFromSource(src capture.Source) error
- func (m *MockSource) CanAddPackets() bool
- func (m *MockSource) Close() error
- func (m *MockSource) Done()
- func (m *MockSource) FinalizeBlock(force bool)
- func (m *MockSource) ForceBlockRelease()
- func (m *MockSource) ForceBlockskUnavailable()
- func (m *MockSource) PacketAddCallbackFn(fn func(payload []byte, totalLen uint32, pktType, ipLayerOffset byte)) *MockSource
- func (m *MockSource) Pipe(src capture.Source, doneReadingChan chan struct{}) (errChan chan error)
- func (m *MockSource) Run() <-chan error
- type MockSourceNoDrain
- type Option
- type Source
- func (s *Source) Close() error
- func (s *Source) Link() *link.Link
- func (s *Source) NewPacket() capture.Packet
- func (s *Source) NextIPPacket(pBuf capture.IPLayer) (ipLayer capture.IPLayer, pktType capture.PacketType, pktLen uint32, err error)
- func (s *Source) NextIPPacketZeroCopy() (ipLayer capture.IPLayer, pktType capture.PacketType, pktLen uint32, err error)
- func (s *Source) NextPacket(pBuf capture.Packet) (pkt capture.Packet, err error)
- func (s *Source) NextPacketFn(...) error
- func (s *Source) NextPayload(pBuf []byte) (payload []byte, pktType capture.PacketType, pktLen uint32, err error)
- func (s *Source) NextPayloadZeroCopy() (payload []byte, pktType capture.PacketType, pktLen uint32, err error)
- func (s *Source) Stats() (capture.Stats, error)
- func (s *Source) Unblock() error
Constants ¶
const (
DefaultSnapLen = (1 << 16) // DefaultSnapLen : 64 kiB
)
Variables ¶
var ( // ErrMockBufferNotPopulated signifies that the mock ring buffer is being run in no drain // mode although not being fully populated (which will most likely lead to issues when // consuming from it) ErrMockBufferNotPopulated = errors.New("mock ring buffer not fully populated, cannot run in no drain mode") )
Functions ¶
This section is empty.
Types ¶
type MockSource ¶
type MockSource struct { *Source MockFd *socket.MockFileDescriptor // contains filtered or unexported fields }
MockSource denotes a fully mocked ring buffer source, behaving just like one Since it wraps a regular Source, it can be used as a stand-in replacement without any further code modifications:
src, err := afring.NewSource("eth0", <options>...) ==> src, err := afring.NewMockSource("eth0", <options>...)
func NewMockSource ¶
func NewMockSource(_ string, options ...Option) (*MockSource, error)
NewMockSource instantiates a new mock ring buffer source, wrapping a regular Source
func (*MockSource) AddPacket ¶
func (m *MockSource) AddPacket(pkt capture.Packet) error
AddPacket adds a new mock packet to the source This can happen prior to calling run or continuously while consuming data, mimicking the function of an actual ring buffer. Consequently, if the ring buffer is full and elements not yet consumed this function may block
func (*MockSource) AddPacketFromSource ¶
func (m *MockSource) AddPacketFromSource(src capture.Source) error
AddPacketFromSource consumes a single packet from the provided source and adds it to the source This can happen prior to calling run or continuously while consuming data, mimicking the function of an actual ring buffer. Consequently, if the ring buffer is full and elements not yet consumed this function may block
func (*MockSource) CanAddPackets ¶
func (m *MockSource) CanAddPackets() bool
CanAddPackets returns if any more packets can be added to the mock source (allowing to non-blockingly assert if the buffer / channel is full or will be on the next operation)
func (*MockSource) Close ¶
func (m *MockSource) Close() error
Close stops / closes the capture source
func (*MockSource) Done ¶
func (m *MockSource) Done()
Done notifies the mock source that no more mock packets will be added, causing the ring buffer filling routine / channel to terminate once all packets have been written to the ring buffer
func (*MockSource) FinalizeBlock ¶
func (m *MockSource) FinalizeBlock(force bool)
FinalizeBlock flushes the current block buffer and puts it onto the channel for consumption
func (*MockSource) ForceBlockRelease ¶
func (m *MockSource) ForceBlockRelease()
ForceBlockRelease releases all blocks to the kernel (in order to "unblock" any potential mock capture from the consuming routine without having to attempt a failed packet consumption)
func (*MockSource) ForceBlockskUnavailable ¶
func (m *MockSource) ForceBlockskUnavailable()
ForceBlockskUnavailable marks all blocks to be unavailable (in order to prevent any access to blocks potentially unconsumed at / after a point in time where this method is called)
func (*MockSource) PacketAddCallbackFn ¶
func (m *MockSource) PacketAddCallbackFn(fn func(payload []byte, totalLen uint32, pktType, ipLayerOffset byte)) *MockSource
PacketAddCallbackFn provides an optional callback function that is called when a packet is added to the mock source (e.g. to build a reference for comparison)
func (*MockSource) Pipe ¶
func (m *MockSource) Pipe(src capture.Source, doneReadingChan chan struct{}) (errChan chan error)
Pipe continuously pipes packets from the provided source through this one, mimicking the ring buffer / TPacketHeader block retirement setting for population of the ring buffer
func (*MockSource) Run ¶
func (m *MockSource) Run() <-chan error
Run executes processing of packets in the background, mimicking the function of an actual kernel packet ring buffer
type MockSourceNoDrain ¶
type MockSourceNoDrain struct { *MockSource // contains filtered or unexported fields }
MockSourceNoDrain denotes a fully mocked, high-throughput ring buffer source, behaving just like one with the notable exception that blocks / packets are not drained but reused instead. Since it wraps a regular Source, it can be used as a stand-in replacement without any further code modifications:
src, err := afring.NewSource("eth0", <options>...) ==> src, err := afring.NewMockSourceNoDrain("eth0", <options>...)
func NewMockSourceNoDrain ¶
func NewMockSourceNoDrain(iface string, options ...Option) (*MockSourceNoDrain, error)
NewMockSourceNoDrain instantiates a new high-throughput mock ring buffer source, wrapping a regular Source
func (*MockSourceNoDrain) Close ¶
func (m *MockSourceNoDrain) Close() error
Close stops / closes the capture source
func (*MockSourceNoDrain) Done ¶
func (m *MockSourceNoDrain) Done()
Done notifies the mock source that no more mock packets will be added, causing the ring buffer filling routine to terminate
func (*MockSourceNoDrain) Run ¶
func (m *MockSourceNoDrain) Run(releaseInterval time.Duration) (<-chan error, error)
Run acts as a high-throughput mode to allow continuous reading the same data currently in the mock buffer without consuming it and with minimal overhead from handling the mock socket / semaphore It is intended to be used in benchmarks using the mock source to minimize measurement noise from the mock implementation itself
type Option ¶
type Option func(*Source)
Option denotes a functional option for the Source
func BufferSize ¶
BufferSize sets the block size / number of blocks for the ring buffer
func CaptureLength ¶
func CaptureLength(strategy link.CaptureLengthStrategy) Option
CaptureLength sets a snapLen / capture length (max. number of bytes captured per packet)
func Promiscuous ¶
Promiscuous enables / disables promiscuous capture mode
type Source ¶
Source denotes an AF_PACKET capture source making use of a ring buffer
func NewSourceFromLink ¶
NewSourceFromLink instantiates a new AF_PACKET capture source making use of a ring buffer taking an existing link instance
func (*Source) NewPacket ¶
NewPacket creates an empty "buffer" packet to be used as destination for the NextPacket() / NextPayload() / NextIPPacket() methods (the latter two by calling .Payload() / .IPLayer() on the created buffer). It ensures that a valid packet of appropriate structure / length is created
func (*Source) NextIPPacket ¶
func (s *Source) NextIPPacket(pBuf capture.IPLayer) (ipLayer capture.IPLayer, pktType capture.PacketType, pktLen uint32, err error)
NextIPPacket receives the IP layer of the next packet from the source and returns it. The operation is blocking. In case a non-nil "buffer" IPLayer is provided it will be populated with the data (and returned). The buffer can be reused. Otherwise a new IPLayer is allocated.
func (*Source) NextIPPacketZeroCopy ¶
func (s *Source) NextIPPacketZeroCopy() (ipLayer capture.IPLayer, pktType capture.PacketType, pktLen uint32, err error)
NextIPPacketZeroCopy receives the IP layer of the next packet from the source and returns it. The operation is blocking. The returned IPLayer provides direct zero-copy access to the underlying data source (e.g. a ring buffer). Procedurally, the method extracts the next packet from either the current block or advances to the next one (fetching / returning its first packet IP layer).
func (*Source) NextPacket ¶
NextPacket receives the next packet from the source and returns it. The operation is blocking. In case a non-nil "buffer" Packet is provided it will be populated with the data (and returned). The buffer packet can be reused. Otherwise a new Packet is allocated.
func (*Source) NextPacketFn ¶
func (s *Source) NextPacketFn(fn func(payload []byte, totalLen uint32, pktType capture.PacketType, ipLayerOffset byte) error) error
NextPacketFn executes the provided function on the next packet received on the source. If possible, the operation should provide a zero-copy way of interaction with the payload / metadata. All operations on the data must be completed prior to any subsequent call to any Next*() method.
func (*Source) NextPayload ¶
func (s *Source) NextPayload(pBuf []byte) (payload []byte, pktType capture.PacketType, pktLen uint32, err error)
NextPayload receives the raw payload of the next packet from the source and returns it. The operation is blocking. In case a non-nil "buffer" byte slice / payload is provided it will be populated with the data (and returned). The buffer can be reused. Otherwise a new byte slice / payload is allocated.
func (*Source) NextPayloadZeroCopy ¶
func (s *Source) NextPayloadZeroCopy() (payload []byte, pktType capture.PacketType, pktLen uint32, err error)
NextPayloadZeroCopy receives the raw payload of the next packet from the source and returns it. The operation is blocking. The returned payload provides direct zero-copy access to the underlying data source (e.g. a ring buffer). Procedurally, the method extracts the next packet from either the current block or advances to the next one (fetching / returning its first packet).