capture

package
v0.83.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2026 License: BSD-3-Clause Imports: 18 Imported by: 0

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

View Source
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 ExecFunc

type ExecFunc func(ctx context.Context, f func(ns.NetNS) error) error

ExecFunc runs f in the network namespace of a node.

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) Close

func (o *Output) Close() error

Close writes the packets still held back and returns the first write error.

func (*Output) Emit

func (o *Output) Emit(id uint32, packet *Packet) (bool, error)

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.

func (*Output) Hold

func (o *Output) Hold(key any, timestamp int64)

Hold keeps packets stamped after timestamp back until Release(key).

func (*Output) Release

func (o *Output) Release(key any)

Release removes the hold of key.

func (*Output) Written

func (o *Output) Written() int64

Written returns the number of packets handed to the stream so far.

type Packet

type Packet struct {
	InterfaceID    uint32
	Timestamp      int64
	OriginalLength uint32
	Data           []byte
}

Packet is an Enhanced Packet Block with its timestamp in nanoseconds.

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.

func NewReader

func NewReader(r io.Reader) *Reader

NewReader returns a reader of the pcapng stream r.

func (*Reader) Next

func (p *Reader) Next() (Event, error)

Next returns the next interface or packet, skipping other block types. It returns io.EOF at the clean end of the stream, and io.ErrUnexpectedEOF for a stream cut inside a block.

func (*Reader) Sections

func (p *Reader) Sections() int

Sections returns the number of Section Header Blocks read so far.

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.

func (*Reorder) Hold

func (q *Reorder) Hold(key any, timestamp int64)

hold keeps packets stamped after timestamp in the buffer until release(key).

func (*Reorder) Push

func (q *Reorder) Push(id uint32, packet *Packet) error

push hands a packet to the buffer. It returns the error of a failed write.

func (*Reorder) Release

func (q *Reorder) Release(key any)

release removes the hold of key.

func (*Reorder) Run

func (q *Reorder) Run(ctx context.Context)

run writes due packets until ctx ends.

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 NewWriter

func NewWriter(w io.Writer) *Writer

NewWriter returns a writer of one pcapng section to w.

func (*Writer) Err

func (p *Writer) Err() error

Err returns the first write error, or nil.

func (*Writer) WriteHeader

func (p *Writer) WriteHeader(names []string, snapLength uint32) error

WriteHeader writes the Section Header Block and one Interface Description Block per name, in order; packets refer to the interfaces by that index.

func (*Writer) WritePacket

func (p *Writer) WritePacket(interfaceID uint32, packet *Packet) error

WritePacket writes an Enhanced Packet Block for the interface with the given index.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL