Skip to content

cmd/tailcat, internal/perf: add iperf-like perf command and service - #131

Merged
bradfitz merged 1 commit into
mainfrom
bradfitz/perf
Sep 23, 2026
Merged

bradfitz merged 1 commit into
mainfrom
bradfitz/perf

Conversation

@bradfitz

Copy link
Copy Markdown
Member

Add "tailcat perf " and a matching "perf" service for
"tailcat serve" to measure what a tunnel can carry: TCP or UDP
throughput in either or both directions, with one or more parallel
streams, for a duration or a byte count. UDP tests report loss,
reordering, and RFC 3550 jitter from a sequence number and send
timestamp in each datagram. All tests report round-trip latency
measured over the test's control connection while the data streams
are running, which is the number that matters when a full pipe makes
everything else sluggish.

The protocol lives in internal/perf. The client opens a JSON-lines
control connection to TCP port 5201 on the server's tailcat address,
data flows on separate TCP connections or UDP flows to the same port,
and each side reports what it sent and received so the client prints
both views of every direction. The server runs one test at a time
and bounds stream count and duration. The service plugs into the
existing OnTCP and OnUDP hooks with the packet filter narrowed to
that port, and logs one line per completed test.

A throughput test through a shared DERP relay mostly measures the
relay's rate limit while crowding out everyone else on it, so the
client waits for a direct path first (up to --timeout, like
ping --until-direct) and refuses to run relayed. --via-derp allows a
relayed test through a relay the user runs, but never through one
under ipn.dev or tailscale.com. Client.DERPRegion is added to the
library so the CLI can see which relay is in use.

Add "tailcat perf <tc-addr>" and a matching "perf" service for
"tailcat serve" to measure what a tunnel can carry: TCP or UDP
throughput in either or both directions, with one or more parallel
streams, for a duration or a byte count. UDP tests report loss,
reordering, and RFC 3550 jitter from a sequence number and send
timestamp in each datagram. All tests report round-trip latency
measured over the test's control connection while the data streams
are running, which is the number that matters when a full pipe makes
everything else sluggish.

The protocol lives in internal/perf. The client opens a JSON-lines
control connection to TCP port 5201 on the server's tailcat address,
data flows on separate TCP connections or UDP flows to the same port,
and each side reports what it sent and received so the client prints
both views of every direction. The server runs one test at a time
and bounds stream count and duration. The service plugs into the
existing OnTCP and OnUDP hooks with the packet filter narrowed to
that port, and logs one line per completed test.

A throughput test through a shared DERP relay mostly measures the
relay's rate limit while crowding out everyone else on it, so the
client waits for a direct path first (up to --timeout, like
ping --until-direct) and refuses to run relayed. --via-derp allows a
relayed test through a relay the user runs, but never through one
under ipn.dev or tailscale.com. Client.DERPRegion is added to the
library so the CLI can see which relay is in use.

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
@bradfitz
bradfitz merged commit 83921d7 into main Sep 23, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant