Documentation
¶
Overview ¶
Package capture writes the pcapng streams of `containerlab capture`: one section with one interface per capture target, packets merged across targets in timestamp order. The local capturer reads lab link interfaces of Docker and Podman nodes through packet sockets; the c9s lab runtime feeds the same writer from clabwire streams.
Index ¶
- Constants
- func CaptureLocal(ctx context.Context, req clablabruntime.CaptureRequest, targets []LocalTarget, ...) error
- func DescribeInterfaces(entries []clablabruntime.CaptureInterface) string
- func FindInterface(entries []clablabruntime.CaptureInterface, name string) (clablabruntime.CaptureInterface, bool)
- func ReportGap(onGap func(clablabruntime.CaptureGap), gap clablabruntime.CaptureGap)
- func ValidateRequest(req *clablabruntime.CaptureRequest) error
- type Event
- type ExecFunc
- type InterfaceDescription
- type LocalTarget
- type Output
- type Packet
- type Reader
- type Reorder
- type Writer
Constants ¶
const ( // DefaultSnapLength is the snap length of a request without one. DefaultSnapLength = 256 << 10 MinSnapLength = 64 MaxSnapLength = 1 << 20 )
Snap length bounds of a capture.
Variables ¶
This section is empty.
Functions ¶
func CaptureLocal ¶
func CaptureLocal( ctx context.Context, req clablabruntime.CaptureRequest, targets []LocalTarget, w io.Writer, ) error
CaptureLocal streams pcapng from interfaces of nodes on this machine to w, with the same output and end conditions as labruntime.PacketCapturer.Capture: one section, one Interface Description Block per target named <node>:<interface>, then the packets of every target in timestamp order. targets lists the interfaces of req.Targets, resolved, in the same order.
Each interface is read through a packet socket opened in the node's network namespace, so nothing runs in the node and the node image needs no capture tools; it needs CAP_NET_RAW and the right to enter the namespace, so root. An interface that goes down is reopened once it is up again; one that disappears (its node stopped or was recreated) is reattached when it is back, and the time it was gone is reported as a gap through req.OnGap (or logged).
func DescribeInterfaces ¶
func DescribeInterfaces(entries []clablabruntime.CaptureInterface) string
DescribeInterfaces lists interfaces for an error message: name (alias), ...
func FindInterface ¶
func FindInterface( entries []clablabruntime.CaptureInterface, name string, ) (clablabruntime.CaptureInterface, bool)
FindInterface matches a requested interface by its name, then by its alias.
func ReportGap ¶
func ReportGap(onGap func(clablabruntime.CaptureGap), gap clablabruntime.CaptureGap)
ReportGap hands a gap to onGap, or logs it as a warning when onGap is nil.
func ValidateRequest ¶
func ValidateRequest(req *clablabruntime.CaptureRequest) error
ValidateRequest checks the bounds of a capture request and fills the default snap length.
Types ¶
type Event ¶
type Event struct {
Interface *InterfaceDescription
Packet *Packet
}
Event is one block of interest: a new interface or a packet.
type InterfaceDescription ¶
type InterfaceDescription struct {
LinkType uint16
SnapLength uint32
Name string
// TSResol is the raw if_tsresol value; 6 (microseconds) when the block has none.
TSResol byte
}
InterfaceDescription is an Interface Description Block.
type LocalTarget ¶
type LocalTarget struct {
// Node is the node name as the topology spells it.
Node string
// Interface is the interface name inside the node.
Interface string
// Exec runs a function in the node's network namespace.
Exec ExecFunc
}
LocalTarget is one interface of a node on this machine (Docker or Podman) to capture.
type Output ¶
type Output struct {
// contains filtered or unexported fields
}
Output is the merged pcapng stream of one capture: the section header with one interface per capture target, then the packets of every target in timestamp order (through a Reorder), up to an optional packet limit.
func NewOutput ¶
func NewOutput( w io.Writer, names []string, snapLength, packetLimit int, window time.Duration, stop func(), ) (*Output, error)
NewOutput writes the section header and one Interface Description Block per name to w, then starts the reorder buffer with the given window (zero or less writes packets as they come). stop is called once the packet limit is reached or a write failed. Close must be called.
func (*Output) Emit ¶
Emit hands a packet of the interface with the given index to the stream. It reports false once the packet limit is reached and the capture stops, and returns the error of a failed write.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader reads the blocks of a pcapng stream as clabwire writes it: one or more little-endian sections, each with its Interface Description Blocks before its packets.
type Reorder ¶
type Reorder struct {
// contains filtered or unexported fields
}
Reorder writes the packets of several capture sources in timestamp order.
Each source (a node's capture stream, or a local interface socket) delivers its packets with its own delay. The buffer holds every packet for `window` after it arrived and writes the held packets in timestamp order, so a packet that was stamped earlier but delivered up to `window` later still goes out first. A packet stamped before the last packet written arrived too late to be ordered: it is written as it comes and counted, and the count goes to the debug log when the capture ends.
A source can place a hold at the earliest timestamp it may still write (Hold); packets stamped after a hold wait for it to be released (Release). The c9s runtime holds while it switches between chained capture segments.
func NewReorder ¶
func NewReorder( window time.Duration, write func(id uint32, packet *Packet) error, onFail func(), ) *Reorder
NewReorder returns a buffer that writes through write; onFail is called once a write failed. A window of zero or less writes every packet as it arrives.
func (*Reorder) Flush ¶
func (q *Reorder) Flush()
flush writes every remaining packet in timestamp order and logs what could not be ordered.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer writes one little-endian section with nanosecond timestamps. Every block goes out in one Write under a lock, so concurrent writers never interleave blocks and a stream cut between writes is still a valid capture.
func (*Writer) WriteHeader ¶
WriteHeader writes the Section Header Block and one Interface Description Block per name, in order; packets refer to the interfaces by that index.