twamp

package module
v0.0.0-...-61225e5 Latest Latest
Warning

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

Go to latest
Published: Jun 16, 2025 License: MIT Imports: 10 Imported by: 0

README

TWAMP

A minimal TWAMP Light implementation in Go for active round-trip time (RTT) measurement over UDP. It follows the TWAMP-Test packet format from RFC 5357 §4.1.2 and uses NTP-style 64-bit timestamps.

Features

  • Sends and receives TWAMP-Test packets over UDP
  • NTP-based timestamps for accurate RTT
  • Summary statistics including packet loss, min/max/avg RTT, and jitter
  • Simple Sender and Reflector interfaces
  • Optional Prometheus metrics instrumentation
  • Configurable padding for packet size control
  • Unit tests and fuzz testing

Example

Reflector (Listener)
go func() {
    listener, _ := twamp.NewListener(":9000", 512, nil, nil)
    _ = listener.Run()
}()
Sender (Client)
sender, _ := twamp.NewSender(":0", "127.0.0.1:9000", time.Second, nil, nil)
res, _ := sender.SendProbe()
fmt.Printf("RTT = %v (seq %d)\n", res.RTT, res.Seq)

Packet Flow Diagram (TWAMP Light)

+---------+                                 +------------+
| Sender  | -- TWAMP-Test packet (UDP) -->  | Reflector  |
|         |                                 |            |
|         | <-- echoed with timestamp ----- |            |
+---------+                                 +------------+

Interfaces

type Sender interface {
	SendProbe() (*ProbeResult, error)
	SendProbeWithPadding(paddingLen int) (*ProbeResult, error)
	Summary() *ProbeSummary
	Close() error
}

type Reflector interface {
    HandleProbe(msg []byte, from net.Addr) ([]byte, error)
}

type Listener interface {
    Run() error
    Close() error
    LocalAddr() net.Addr
}

TWAMP-Test Packet Format

This library uses the minimal TWAMP-Test format (RFC 5357 §4.1.2):

Field Offset Size (bytes)
Sequence Number 0 4
Timestamp (seconds) 4 4
Timestamp (fraction) 8 4
Error Estimate 12 2
MBZ (reserved) 14 2
Reflector TS (sec) 16 4
Reflector TS (frac) 20 4
Padding 24 variable

Timestamps follow NTP 64-bit format: 32 bits for seconds, 32 bits for fractional seconds since Jan 1, 1900 UTC.

Output Example

RTT = 212.400µs (seq 4)

Limitations (Not Yet Implemented)

This library implements the essentials of TWAMP Light. Some features are not yet included:

  • DSCP / TOS field configuration
  • Don't Fragment (DF) bit
  • CLI tools (twamp-client, twamp-reflector)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FromNTP

func FromNTP(secs, frac uint32) time.Time

func ToNTP

func ToNTP(t time.Time) (uint32, uint32)

Types

type Listener

type Listener interface {
	Run(ctx context.Context) error
	Close() error
	LocalAddr() net.Addr
}

func NewListener

func NewListener(addr string, bufsize int, log *slog.Logger, metrics *MetricsCollector) (Listener, error)

type MetricsCollector

type MetricsCollector struct {
	ProbesSent     prometheus.Counter
	ProbesReceived prometheus.Counter
	RTT            prometheus.Histogram
	PacketsDropped prometheus.Counter
}

MetricsCollector holds Prometheus metrics for TWAMP traffic.

func NewMetricsCollector

func NewMetricsCollector() *MetricsCollector

func (*MetricsCollector) Register

func (m *MetricsCollector) Register(reg prometheus.Registerer)

type ProbeResult

type ProbeResult struct {
	Seq      uint32        `json:"seq"`
	RTT      time.Duration `json:"rtt"`
	Sent     time.Time     `json:"sent"`
	Received time.Time     `json:"received"`
}

type ProbeSummary

type ProbeSummary struct {
	Count    int
	Lost     int
	MinRTT   time.Duration
	MaxRTT   time.Duration
	TotalRTT time.Duration
	Jitter   time.Duration
	LastRTT  time.Duration
	// contains filtered or unexported fields
}

func (*ProbeSummary) AvgRTT

func (s *ProbeSummary) AvgRTT() time.Duration

func (*ProbeSummary) Update

func (s *ProbeSummary) Update(rtt time.Duration, ok bool)

type Reflector

type Reflector interface {
	HandleProbe([]byte, net.Addr) ([]byte, error)
}

func NewReflector

func NewReflector(log *slog.Logger, metrics *MetricsCollector) Reflector

type Sender

type Sender interface {
	SendProbe() (*ProbeResult, error)
	SendProbeWithPadding(paddingLen int) (*ProbeResult, error)
	Close() error
	Summary() *ProbeSummary
	ResetSummary()
}

func NewSender

func NewSender(local, remote string, timeout time.Duration, log *slog.Logger, metrics *MetricsCollector) (Sender, error)

type TestPacket

type TestPacket struct {
	Seq               uint32
	TimestampSec      uint32
	TimestampFrac     uint32
	ErrorEstimate     uint16
	MBZ               uint16
	RecvTimestampSec  uint32
	RecvTimestampFrac uint32
	Padding           []byte
}

func UnmarshalTestPacket

func UnmarshalTestPacket(buf []byte) (*TestPacket, error)

func (*TestPacket) MarshalBinary

func (p *TestPacket) MarshalBinary() []byte

Jump to

Keyboard shortcuts

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