antler

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2023 License: GPL-3.0 Imports: 25 Imported by: 0

README

Antler

Antler is a tool for network and congestion control testing. The name stands for Active Network Tester of Load & Response, where '&' == Et. :)

Introduction

Antler grew out of testing needs that arose during work on SCE, and related congestion control projects in the IETF. It can be used to set up and tear down test environments, coordinate traffic flows across multiple nodes, gather data using external tools like tcpdump, and generate reports and plots from the results.

Features

  • support for tests using stream-oriented and packet-oriented protocols (for now, TCP and UDP)
  • auto-installed test nodes that run either locally or via ssh, and optionally in Linux network namespaces
  • configurable hierarchy of "runners", that may execute in serial or parallel across nodes
  • runner scheduling with arbitrary timing (e.g. TCP flow introductions on an exponential distribution with lognormal lengths)
  • configurable UDP packet release times and lengths, supporting from isochronous to VBR or bursty traffic, or combinations in one flow
  • system runner for system commands, e.g. for setup, teardown, data collection, and mid-test config changes
  • parallel execution of entire tests, with nested serial and parallel test runs
  • result streaming during test (may be enabled, disabled or configured to deliver only some results, e.g. just logs, but not pcaps)
  • plots/reports using Go templates, with included templates for time series and FCT plots using Google Charts
  • configuration using CUE, to support test parameter combinations, config schema definition, data validation and config reuse

Examples

Example Plot
fct fct
ratedrop timeseries
sceaqm cake / cnq_cobalt / codel / pfifo / pie / cobalt / deltic
tcpstream timeseries
vbrudp timeseries

To run the examples yourself, e.g.:

cd examples/tcpstream
sudo antler run

All configuration is in the .cue or .cue.tmpl files. Root access is required for any examples that need to create network namespaces.

The antler binary must be in your PATH, or the full path must be specified. Typically, you add ~/go/bin to your PATH so you can run binaries installed by Go. Note: if using sudo and the secure_path option is set in /etc/sudoers, either this must be added to that path, or additional configuration is required.

Installation

Using go install
  1. Install Go.
  2. go install github.com/heistp/antler@latest
  3. make (builds node binaries, installs antler command)
Using git clone
  1. Install Go.
  2. cd
  3. mkdir -p go/src/github.com/heistp
  4. cd go/src/github.com/heistp
  5. git clone https://github.com/heistp/antler
  6. cd antler
  7. make (builds node binaries, installs antler command)

Documentation

At present, Antler is documented through the examples, and the comments in config.cue. Antler is configured using CUE, so it helps to get familiar with the language at a basic level, although for simple tests it may be sufficient to just follow the examples.

Status

As of version 0.3.0, the node is working, along with some basic tests and visualizations. The Roadmap shows future plans. Overall, more work is needed on the tests and visualizations, stabilizing the config and data formats, and supporting platforms other than Linux.

Roadmap

Version 1.0.0
  • add standard reports for each test:
    • node logs and system information
    • time series and FCT plots
    • tables of standard flow metrics: goodput, FCT, RTT distributions, etc
    • an HTML index of tests and results
  • add support for sampling Linux socket stats via netlink (in C)
  • implement incremental test runs using hard links
  • implement timeouts, both for runners and the node control connection
  • complete the SSH launcher, with sudo support, and add an example of its use
  • for packet flows:
    • record replies and calculate RTT
    • detect lost and late (out of order) packets
  • handle tests both with and without node-synchronized time
  • add support for setting arbitary sockopts
  • add sorting by time for saved log files
  • secure the servers for use on the Internet
  • add compression support for System runner FileData output
  • make UDP flood more efficient
  • add an antler init command to create a default project
  • write documentation (in markdown)
Version 0.4.0
Features
  • refactor examples to share common setup
  • move SCE examples into sce-tests repo
  • build examples to a public server and remove from README
Bugs
  • improve poor error messages from CUE for syntax errors under disjunctions (e.g. when Env length > max- Run.Test: field not allowed)
Inbox
Features
  • improve semantics for System.Stdout and Stderr
  • add ability to save System Stdout directly to local file
  • add ability to buffer System Stdout to a tmp file before sending as FileData
  • implement flagForward optimization, and maybe invert it to flagProcess
  • add support for simulating conversational stream protocols
  • show bandwidth for FCT distribution
  • find a better way than unions to create interface implementations from CUE
  • allow Go template syntax right in .cue files, instead of using .cue.tmpl files
  • support multiple nodes in the same namespace
  • add Antler to CUE Unity
  • support MacOS
  • support FreeBSD

Thanks

Thanks to sponsors, and Jonathan Morton and Rodney Grimes for advice and patience.

NGI SCE Sticker

RIPE NCC

Documentation

Index

Constants

View Source
const Version = "0.3.0"

Version represents the Antler version.

Variables

This section is empty.

Functions

func Run

func Run(cmd Command) error

Run runs an Antler Command.

Types

type AmbiguousNodeIDError

type AmbiguousNodeIDError struct {
	ID []node.NodeID
}

AmbiguousNodeIDError is returned when multiple Nodes use the same ID but with different field values.

func (*AmbiguousNodeIDError) Error

func (a *AmbiguousNodeIDError) Error() string

type AndFilter

type AndFilter []TestFilter

AndFilter accepts a Test if each of its TestFilters accepts it.

func (AndFilter) Accept

func (a AndFilter) Accept(test *Test) bool

Accept implements TestFilter

type ChartsFCT

type ChartsFCT struct {
	// To lists the names of files to execute the template to. A file of "-"
	// emits to stdout.
	To []string

	// Series matches Flows to series.
	Series []FlowSeries

	// Options is an arbitrary structure of Charts options, with defaults
	// defined in config.cue.
	// https://developers.google.com/chart/interactive/docs/gallery/scatterchart#configuration-options
	Options map[string]interface{}
}

ChartsFCT is a reporter that makes time series plots using Google Charts.

type ChartsTCPInfo

type ChartsTCPInfo struct {
	// FlowLabel sets custom labels for Flows.
	FlowLabel map[node.Flow]string

	// To lists the names of files to execute the template to. A file of "-"
	// emits to stdout.
	To []string

	// Options is an arbitrary structure of Charts options, with defaults
	// defined in config.cue.
	// https://developers.google.com/chart/interactive/docs/gallery/linechart#configuration-options
	Options map[string]interface{}
}

ChartsTCPInfo is a reporter that makes TCPInfo plots using Google Charts.

type ChartsTimeSeries

type ChartsTimeSeries struct {
	// FlowLabel sets custom labels for Flows.
	FlowLabel map[node.Flow]string

	// To lists the names of files to execute the template to. A file of "-"
	// emits to stdout.
	To []string

	// Options is an arbitrary structure of Charts options, with defaults
	// defined in config.cue.
	// https://developers.google.com/chart/interactive/docs/gallery/linechart#configuration-options
	Options map[string]interface{}
}

ChartsTimeSeries is a reporter that makes time series plots using Google Charts.

type Command

type Command interface {
	// contains filtered or unexported methods
}

A Command is an Antler command.

type Config

type Config struct {
	// Run is the top-level TestRun instance.
	Run TestRun
}

Config is the Antler configuration, loaded from CUE.

func LoadConfig

func LoadConfig(cuecfg *load.Config) (cfg *Config, err error)

LoadConfig first executes templates in any .cue.tmpl files to create the corresponding .cue files, then uses the CUE API to load and return the Antler Config.

type DuplicateTestIDError

type DuplicateTestIDError struct {
	ID []TestID
}

DuplicateTestIDError is returned when multiple Tests have the same ID.

func (*DuplicateTestIDError) Error

func (d *DuplicateTestIDError) Error() string

type EmitLog

type EmitLog struct {
	// To lists the destinations to send output to. "-" sends output to stdout,
	// and everything else sends output to the named file. If To is empty,
	// output is emitted to stdout.
	To []string
}

EmitLog is a reporter that emits LogEntry's to files and/or stdout.

type EmitTCPInfo

type EmitTCPInfo struct {
	// To lists the destinations to send output to. "-" sends output to stdout,
	// and everything else sends output to the named file. If To is empty,
	// output is emitted to stdout.
	To []string
}

EmitTCPInfo is a reporter that emits TCPInfo to files and/or stdout.

type FileExistsError

type FileExistsError struct {
	Path string
}

FileExistsError is returned by Writer when the named file already exists, and overwrite is false. The Path field is the path to the file.

func (*FileExistsError) Error

func (f *FileExistsError) Error() string

type FlowSeries

type FlowSeries struct {
	Name    string
	Pattern string
	// contains filtered or unexported fields
}

FlowSeries groups flows into series by matching the Flow ID with a Regex.

func (*FlowSeries) Compile

func (s *FlowSeries) Compile() (err error)

Compile compiles Pattern to a Regexp.

func (*FlowSeries) Match

func (s *FlowSeries) Match(flow node.Flow) (matches bool)

Match returns true if Flow matches Regex.

type NoDataFileError

type NoDataFileError struct {
	Test *Test
}

NoDataFileError is returned by DataWriter ot DataReader when the Test's DataFile field is empty, so no data may be read or written. The Test field is the corresponding Test.

func (*NoDataFileError) Error

func (n *NoDataFileError) Error() string

type OrFilter

type OrFilter []TestFilter

OrFilter accepts a Test if any of its TestFilters accepts it.

func (OrFilter) Accept

func (o OrFilter) Accept(test *Test) bool

Accept implements TestFilter

type Parallel

type Parallel []TestRun

Parallel is a list of TestRun's executed concurrently.

type RegexFilter

type RegexFilter struct {
	Key   *regexp.Regexp
	Value *regexp.Regexp
}

RegexFilter is a TestFilter that matches Tests by their ID using regular expressions. If any of a Test ID's key/value pairs match the non-nil expressions in Key and Value, the Test is accepted. If both Key and Value are nil (i.e. a zero value RegexFilter), all Tests are accepted.

func NewRegexFilterArg

func NewRegexFilterArg(arg string) (flt *RegexFilter, err error)

NewRegexFilterArg returns a new RegexFilter from a string argument. The argument may be either a single pattern matching the value of any ID field, or a string in the form key=value, where key and value are separate patterns that must match both a Test ID key and value for it to be accepted.

func (*RegexFilter) Accept

func (f *RegexFilter) Accept(test *Test) bool

Accept implements antler.TestFilter

type Report

type Report struct {
	// contains filtered or unexported fields
}

Report represents the report configuration.

type ReportCommand

type ReportCommand struct {
	// Filter selects which tests to run.
	Filter TestFilter

	// SkippedFiltered is called when a test was skipped because it was rejected
	// by the Filter.
	SkippedFiltered func(test *Test)

	// SkippedNoDataFile is called when a report was skipped because the Test's
	// DataFile field is empty.
	SkippedNoDataFile func(test *Test)

	// SkippedNotFound is called when a report was skipped because the data file
	// needed to run it doesn't exist.
	SkippedNotFound func(test *Test, path string)
}

ReportCommand runs reports.

type RunCommand

type RunCommand struct {
	// Control is used to send node control signals.
	Control node.Control

	// Force re-runs the test and overwrites any existing data.
	Force bool

	// Filter selects which tests to run.
	Filter TestFilter

	// SkippedFiltered is called when a test was skipped because it was rejected
	// by the Filter.
	SkippedFiltered func(test *Test)

	// SkippedDataFileExists is called when a test was skipped because there's
	// already an output data file for it and RunCommand.Force is false.
	SkippedDataFileExists func(test *Test, path string)
}

RunCommand runs tests and reports.

type SaveFiles

type SaveFiles struct {
}

SaveFiles is a reporter that saves FileData.

type Serial

type Serial []TestRun

Serial is a list of TestRun's executed sequentially.

type Test

type Test struct {
	// ID uniquely identifies the Test in the test package.
	ID TestID

	// OutputPrefix is the base path for output files. It may use Go template
	// syntax, and is further documented in config.cue.
	OutputPrefix string

	// DataFile is the name of the gob output file containing the raw result
	// data. If empty, raw result data is not saved for the Test.
	DataFile string

	// Run is the top-level Run instance.
	node.Run

	// Report lists Reports to be run on this Test.
	Report reports
}

Test is an Antler test.

func (*Test) DataReader

func (t *Test) DataReader() (rc io.ReadCloser, err error)

DataReader returns a ReadCloser for reading result data.

If DataFile is empty, NoDataFileError is returned.

If the data file does not exist, errors.Is(err, fs.ErrNotExist) returns true.

func (*Test) DataWriter

func (t *Test) DataWriter(overwrite bool) (wc io.WriteCloser, err error)

DataWriter returns a WriteCloser for writing result data.

The overwrite parameter indicates whether to overwrite existing data (if true), or not (if false), in which case FileExistsError is returned if the file referred to by DataFile already exists.

If DataFile is empty, NoDataFileError is returned.

func (*Test) OutputPath

func (t *Test) OutputPath(name string) (path string, err error)

OutputPath returns the path to an output file, by appending the given name to the base output path generated by OutputPrefix. If name is empty, the base OutputPrefix is returned.

func (*Test) Writer

func (t *Test) Writer(name string, overwrite bool) (wc io.WriteCloser,
	err error)

Writer returns a WriteCloser for writing result data.

The overwrite parameter indicates whether to overwrite an existing file (if true), or not (if false), in which case FileExistsError is returned if the file referred to by name already exists.

Any directories in name are automatically created.

type TestFilter

type TestFilter interface {
	Accept(*Test) bool
}

A TestFilter accepts or rejects Tests.

type TestID

type TestID map[string]string

TestID represents a compound Test identifier. Keys and values must match the regex defined in config.cue.

func (TestID) Equal

func (i TestID) Equal(other TestID) bool

Equal returns true if other is equal to this TestID (they contain the same key/value pairs).

func (TestID) String

func (i TestID) String() string

String returns a canonical version of the Test ID in the form: [K=V ...] with key/value pairs sorted by their keys.

type TestRun

type TestRun struct {
	// Test is the Test to run (non-nil on leaf TestRun's).
	Test *Test

	// Report lists Reports to be run on this TestRun and any below it in the
	// TestRun tree.
	Report reports

	// Serial lists TestRun's to be executed sequentially.
	Serial Serial

	// Parallel lists TestRun's to be executed concurrently.
	Parallel Parallel
}

TestRun contains the information needed to orchestrate the execution of Tests and Reports. A TestRun may have a Test, or nested TestRun's listed in the Serial or Parallel fields, which are executed sequentially or concurrently, respectively. TestRun's may thus be arranged in a hierarchy to coordinate the serial and parallel execution of Tests.

func (*TestRun) VisitTests

func (t *TestRun) VisitTests(visitor func(*Test) bool) bool

VisitTests calls the given visitor func for each Test in the TestRun hierarchy. The visitor may return false to stop visiting, in which case VisitTests will also return false.

type VetCommand

type VetCommand struct {
}

VetCommand loads and checks the CUE config.

Directories

Path Synopsis
cmd
antler command
node command
metric
Package metric provides base types for units, measurement and statistics.
Package metric provides base types for units, measurement and statistics.

Jump to

Keyboard shortcuts

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