rate

package
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package rate implements Wireblast's aggregate packet- and bit-rate limiter.

One Limiter governs the whole run, not one per queue: --pps 1M means a million packets per second in total, whether that is spread over one queue or twelve. Queue workers draw credit in batches, so the shared state is touched once per few hundred packets rather than once per packet, and the steady-state path allocates nothing.

Both limits are token buckets. When both are set a packet needs credit from both, so the binding constraint is simply whichever runs out first. A limit of zero means "no limit" for that bucket; both zero means line rate, which takes a lock-free fast path.

Index

Constants

View Source
const (
	MinWait = 50 * time.Microsecond
	MaxWait = 2 * time.Millisecond
)

Sleep bounds used when a worker has to wait for credit. The lower bound keeps a low-rate run from spinning on the clock; the upper bound keeps rate changes and pause/resume responsive.

Variables

This section is empty.

Functions

This section is empty.

Types

type Grant

type Grant struct {
	// Packets is how many packets may be sent. Zero means no credit yet.
	Packets int
	// contains filtered or unexported fields
}

Grant is permission to transmit, returned by Limiter.Acquire. It carries the estimate the limiter charged for, so Limiter.Settle can correct the accounting once the true sizes are known.

type Limiter

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

Limiter is an aggregate packet/bit rate limiter shared by every queue.

The zero value is not usable; call New.

func New

func New(pps, bps uint64, opts ...Option) *Limiter

New creates a limiter for the given packet and bit rates. Either may be 0, meaning that limit is not enforced; both 0 means unlimited.

The bit rate is measured in on-the-wire bits, so callers should charge each frame its full framing cost (frame bytes + 20) * 8.

func (*Limiter) Acquire

func (l *Limiter) Acquire(maxPackets, wireBytes int) (Grant, time.Duration)

Acquire asks for permission to send up to maxPackets packets, each estimated to cost wireBytes bytes on the wire. It returns a Grant and, when the grant is empty, how long the caller should wait before asking again.

The estimate only has to be close: Limiter.Settle reconciles the bit bucket against the real sizes afterwards, so variable-size traffic (IMIX, PCAP replay) still converges on the requested bit rate.

func (*Limiter) Paused

func (l *Limiter) Paused() bool

Paused reports whether transmission is currently paused.

func (*Limiter) Rate

func (l *Limiter) Rate() (pps, bps uint64)

Rate returns the configured packet and bit rates, 0 meaning unlimited.

func (*Limiter) Reset

func (l *Limiter) Reset()

Reset discards accrued credit and restarts the clock.

The dataplane calls this the moment traffic can actually flow. A limiter built before the XDP program is attached would otherwise spend the several seconds of link bounce quietly accruing credit for packets nothing could have sent.

func (*Limiter) Scale

func (l *Limiter) Scale(factor float64) (pps, bps uint64)

Scale multiplies both limits by factor, which is how the +/- hotkeys adjust the rate. A limit that is unlimited stays unlimited, so which constraint is active does not change. Rates are clamped to at least 1 so repeated decreases cannot reach zero and silently mean "unlimited".

func (*Limiter) SetPaused

func (l *Limiter) SetPaused(p bool)

SetPaused stops or resumes granting. While paused no credit accrues, so a long pause is not followed by a catch-up burst.

func (*Limiter) SetRate

func (l *Limiter) SetRate(pps, bps uint64)

SetRate changes both limits while the run is in flight. Credit already accrued is discarded so the new rate takes effect immediately rather than after a burst at the old one.

func (*Limiter) Settle

func (l *Limiter) Settle(g Grant, sent int, sentWireBytes uint64)

Settle reconciles a grant against what was actually transmitted: sent is how many of the granted packets went out, and sentWireBytes their true total on-the-wire size. Unsent packets are refunded and any difference between the estimate and reality is corrected, which can leave a bucket in debt — that debt is repaid by the next accrual, so the long-run rate stays exact.

Callers may skip Settle when the grant was fully used and the estimate was exact, which is the fixed-size case.

func (*Limiter) Unlimited

func (l *Limiter) Unlimited() bool

Unlimited reports whether neither limit is in force.

type Option

type Option func(*Limiter)

Option configures a Limiter.

func WithBatch

func WithBatch(n int) Option

WithBatch sets the batch size the bucket capacities are sized against. It should match the transmit loop's batch. Default 256.

func WithClock

func WithClock(now func() time.Time) Option

WithClock replaces the time source, for tests.

Jump to

Keyboard shortcuts

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