chore: improve documentation and README
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 33s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 23s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Successful in 33s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m7s
Rust CI / cargo doc (push) Successful in 27s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Successful in 1m21s
Fuzz Smoke / cargo fuzz smoke (push) Successful in 1m40s
Netem Interop / netem interop (push) Successful in 1m18s
Supply chain / cargo-deny advisories (push) Successful in 18s
Supply chain / actionlint (push) Failing after 4s
Supply chain / cargo-deny bans licenses sources (push) Successful in 17s
Build binaries / Build (arm-musleabi) (push) Successful in 4m58s
Build binaries / Build (aarch64-musl) (push) Successful in 5m6s
Build binaries / Build (arm-musleabihf) (push) Successful in 4m38s
Build binaries / Build (armv7-musleabi) (push) Successful in 4m33s
Build binaries / Build (armv7-musleabihf) (push) Successful in 4m57s
Build binaries / Build (i686-musl) (push) Successful in 5m1s
Build binaries / Build (mips64-muslabi64) (push) Successful in 4m35s
Build binaries / Build (mips-musl) (push) Successful in 4m42s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 4m54s
Build binaries / Build (mipsel-musl) (push) Successful in 4m54s
Build binaries / Build (riscv64gc-musl) (push) Successful in 4m36s
Build binaries / Build (x86_64-musl) (push) Successful in 4m40s
Rust CI / cargo fmt (push) Successful in 17s
Rust CI / cargo clippy (push) Successful in 33s
Rust CI / cargo check (x86_64-unknown-linux-gnu) (push) Successful in 23s
Rust CI / cargo check (x86_64-unknown-linux-musl) (push) Successful in 33s
Rust CI / cargo test (x86_64-unknown-linux-gnu) (push) Successful in 1m7s
Rust CI / cargo doc (push) Successful in 27s
Rust CI / cargo test (x86_64-unknown-linux-musl) (push) Successful in 1m21s
Fuzz Smoke / cargo fuzz smoke (push) Successful in 1m40s
Netem Interop / netem interop (push) Successful in 1m18s
Supply chain / cargo-deny advisories (push) Successful in 18s
Supply chain / actionlint (push) Failing after 4s
Supply chain / cargo-deny bans licenses sources (push) Successful in 17s
Build binaries / Build (arm-musleabi) (push) Successful in 4m58s
Build binaries / Build (aarch64-musl) (push) Successful in 5m6s
Build binaries / Build (arm-musleabihf) (push) Successful in 4m38s
Build binaries / Build (armv7-musleabi) (push) Successful in 4m33s
Build binaries / Build (armv7-musleabihf) (push) Successful in 4m57s
Build binaries / Build (i686-musl) (push) Successful in 5m1s
Build binaries / Build (mips64-muslabi64) (push) Successful in 4m35s
Build binaries / Build (mips-musl) (push) Successful in 4m42s
Build binaries / Build (mips64el-muslabi64) (push) Successful in 4m54s
Build binaries / Build (mipsel-musl) (push) Successful in 4m54s
Build binaries / Build (riscv64gc-musl) (push) Successful in 4m36s
Build binaries / Build (x86_64-musl) (push) Successful in 4m40s
This commit is contained in:
6 files changed
+534
-466
No files matched your search
+104
-104
@@ -1,22 +1,22 @@
|
||||
# irtt-server
|
||||
|
||||
## NAME
|
||||
## Name
|
||||
|
||||
irtt-server - IRTT-compatible UDP server
|
||||
|
||||
## SYNOPSIS
|
||||
## Synopsis
|
||||
|
||||
`irtt-server` [`--bind` *ADDR*]... [*OPTIONS*]
|
||||
|
||||
`irtt-rs server` [`--bind` *ADDR*]... [*OPTIONS*]
|
||||
|
||||
## DESCRIPTION
|
||||
## Description
|
||||
|
||||
`irtt-server` answers IRTT echo requests over UDP. It is thin orchestration
|
||||
over the reusable `irtt-server` library: one current-thread Tokio runtime,
|
||||
one or more listeners, and the library's own session/policy logic.
|
||||
`irtt-server` answers IRTT echo requests over UDP. It uses the reusable
|
||||
`irtt-server` library for sessions and policy, with one current-thread
|
||||
Tokio runtime running one or more listeners.
|
||||
|
||||
Run with no arguments for the ordinary case:
|
||||
To start a server with the defaults, run:
|
||||
|
||||
```sh
|
||||
irtt-server
|
||||
@@ -28,34 +28,31 @@ wildcard address for both address families, in this fixed order:
|
||||
1. `[::]:2112`
|
||||
2. `0.0.0.0:2112`
|
||||
|
||||
This is available wherever the platform supports safe wildcard reply-source
|
||||
selection (see [Wildcard binds](#wildcard-binds) below). Any explicit
|
||||
`--bind` **replaces** this default pair entirely rather than adding to it —
|
||||
`irtt-server --bind 127.0.0.1:2112` binds only that one address.
|
||||
The defaults work on platforms that support wildcard reply-source
|
||||
selection (see [Wildcard binds](#wildcard-binds)). If you supply any
|
||||
`--bind`, it replaces both defaults. For example,
|
||||
`irtt-server --bind 127.0.0.1:2112` listens only on that address.
|
||||
|
||||
If one of the two default addresses cannot be bound because its address
|
||||
family itself has no local support at all — IPv6 disabled on an otherwise
|
||||
IPv4-capable host, for example — the server falls back to serving just the
|
||||
other one instead of failing outright, and says so on startup. Any other
|
||||
reason a default listener fails — the port already in use, permission
|
||||
denied, no safe wildcard reply-source path — is not a family-support
|
||||
problem and is not silently worked around; the invocation fails as it would
|
||||
for an explicit `--bind`. This fallback applies only to the implicit default
|
||||
pair: an explicit `--bind` list always keeps the ordinary all-or-nothing
|
||||
behavior described below.
|
||||
If the host has no support for one address family, for example because IPv6
|
||||
is disabled, the server uses the other default listener and tells you on
|
||||
startup. Other bind failures still stop startup. This includes a port
|
||||
already in use, permission denied, or a platform without safe wildcard
|
||||
reply-source selection.
|
||||
|
||||
## OPTIONS
|
||||
The address-family fallback only applies to the default pair. An explicit
|
||||
`--bind` list always uses the all-or-nothing behavior described below.
|
||||
|
||||
## Options
|
||||
|
||||
### `--bind ADDR`
|
||||
|
||||
Local UDP address to bind, as `ADDR:PORT`, for example `127.0.0.1:2112` or
|
||||
`[::1]:2112`. Host names are not resolved. Repeatable.
|
||||
Use `ADDR:PORT` to choose a local UDP address, for example `127.0.0.1:2112`
|
||||
or `[::1]:2112`. Hostnames are not resolved.
|
||||
|
||||
Repeat the option to serve several addresses from one process, in the order
|
||||
given. Every listener applies the same policy options, but each keeps its
|
||||
own sessions and tokens, so a session belongs to the address it was opened
|
||||
on. Binding is all-or-nothing: if any address cannot be bound, none are
|
||||
served.
|
||||
Repeat `--bind` to serve several addresses from one process, in the order
|
||||
given. Every listener uses the same policy options, but keeps its own
|
||||
sessions and tokens. A session belongs to the address it was opened on.
|
||||
Binding is all-or-nothing: if any address cannot be bound, none are served.
|
||||
|
||||
A port of `0` selects an unused port per listener, so two such binds get two
|
||||
different ports.
|
||||
@@ -63,71 +60,75 @@ different ports.
|
||||
With no `--bind` at all, see [Description](#description) above for the
|
||||
default wildcard pair and the address-family fallback it allows.
|
||||
|
||||
When reply DSCP/traffic-class marking for IPv4 peers matters, do not configure
|
||||
one explicit dual-stack `[::]:PORT` listener by itself. On Linux, IPv4 peers
|
||||
served through that socket are IPv4-mapped and their replies cannot retain the
|
||||
negotiated marking. Configure the ordinary paired `[::]:PORT` and
|
||||
`0.0.0.0:PORT` listeners instead; the IPv6 listener is made IPv6-only for that
|
||||
same-port pair, so each family uses the correct socket option. This is a
|
||||
configuration workaround, not a reason to force `IPV6_V6ONLY` for every lone
|
||||
IPv6 listener.
|
||||
If you need DSCP/traffic-class marking on replies to IPv4 peers, use care
|
||||
with a lone dual-stack `[::]:PORT` listener. On Linux, those peers use
|
||||
IPv4-mapped addresses and their replies cannot retain the negotiated
|
||||
marking. Use paired `[::]:PORT` and `0.0.0.0:PORT` listeners on the same
|
||||
port. The server makes the IPv6 listener IPv6-only for that pair, so each
|
||||
family gets the correct socket option. A lone IPv6 listener keeps its usual
|
||||
behavior; the server does not force `IPV6_V6ONLY` on it.
|
||||
|
||||
### `--hmac KEY`
|
||||
|
||||
Accepts a plain-text key or a hexadecimal key prefixed with `0x`. For example, `secret` and `0x736563726574` are equivalent. The `IRTT_SERVER_HMAC` environment variable uses the same syntax.
|
||||
You can use a plain-text key or a hexadecimal key prefixed with `0x`.
|
||||
For example, `secret` and `0x736563726574` are equivalent. The
|
||||
`IRTT_SERVER_HMAC` environment variable accepts the same syntax.
|
||||
|
||||
With a key configured, every request must carry a valid MAC and every reply is authenticated;
|
||||
without one, authenticated requests are dropped. The key is visible in the
|
||||
process arguments.
|
||||
With a key configured, every request must carry a valid MAC and the server
|
||||
authenticates every reply. Without a key, the server drops authenticated
|
||||
requests. A key passed on the command line is visible in the process
|
||||
arguments.
|
||||
|
||||
### `--max-sessions COUNT`
|
||||
|
||||
Maximum number of simultaneously live sessions **per listener**, not per
|
||||
process. Once a listener's table is full, a session-creating open to it is
|
||||
dropped silently; nothing is evicted. Zero refuses every session-creating
|
||||
open.
|
||||
Set the maximum number of live sessions per listener. This limit applies
|
||||
to each listener separately, so the process can have more sessions in total.
|
||||
Once a listener's table is full, it silently drops opens that would create
|
||||
a session and keeps the existing sessions. Zero refuses every open that
|
||||
would create a session.
|
||||
|
||||
### `--max-packet-length BYTES`
|
||||
|
||||
Maximum echo datagram size a session may negotiate, in bytes. A longer
|
||||
requested length is reduced during negotiation, an open whose mandatory
|
||||
field block would not fit is refused, and inbound echo requests are admitted
|
||||
against the same limit. This is a resource bound, not an MTU.
|
||||
Set the maximum echo datagram size a session may negotiate, in bytes. The
|
||||
server reduces longer requests during negotiation and refuses an open if
|
||||
its mandatory fields would not fit. Incoming echo requests must fit the
|
||||
same limit. Use this to bound resource use; it does not set the network MTU.
|
||||
|
||||
### `--min-interval DURATION`
|
||||
|
||||
Floor on the send interval a session may negotiate. The negotiated interval
|
||||
is still capped at a quarter of the idle timeout afterwards, so a
|
||||
`--min-interval` above that cap is not the value actually negotiated.
|
||||
Set the minimum send interval a session may negotiate. The server then caps
|
||||
the negotiated interval at a quarter of the idle timeout, so a
|
||||
`--min-interval` above that cap will be reduced.
|
||||
|
||||
A session's reply allowance refills at the shorter of this configured floor
|
||||
and the interval it actually negotiated. Ordinarily that is the configured
|
||||
floor itself, since the negotiated interval is normally at least as long —
|
||||
a 10ms `--min-interval` against a 1s negotiated interval refills every
|
||||
10ms. The two differ only when the idle-timeout cap above pulled the
|
||||
negotiated interval below the configured floor, in which case the shorter,
|
||||
negotiated value is what the allowance actually refills at: a server must
|
||||
not enforce a cadence it did not advertise to the client. Use `0` for no
|
||||
time-based throttling.
|
||||
The session's reply allowance refills at the shorter of the configured
|
||||
minimum and the negotiated interval. Usually this is the configured
|
||||
minimum: a 10ms `--min-interval` with a 1s negotiated interval refills every
|
||||
10ms.
|
||||
|
||||
If the idle-timeout cap reduces the negotiated interval below the configured
|
||||
minimum, the allowance refills at that shorter interval too. This keeps the
|
||||
server from enforcing a slower cadence than it told the client to use.
|
||||
Use `0` for no time-based throttling.
|
||||
|
||||
### `--burst COUNT`
|
||||
|
||||
Echo replies one session may have answered before its allowance has to
|
||||
refill. Use `0` for no allowance at all, which rate-limits every echo
|
||||
request whatever the interval is.
|
||||
Set how many echo replies a session can send before its allowance needs to
|
||||
refill. Use `0` for no allowance, which rate-limits every
|
||||
echo request regardless of the interval.
|
||||
|
||||
### `--idle-timeout DURATION`
|
||||
|
||||
Release a session after this long without a served or rate-limited echo
|
||||
request. The deadline runs from the open, and release is silent. Use `0` to
|
||||
expire a session at the next evaluation; it is not a way to disable expiry.
|
||||
request. The timeout starts at open, and the server releases the session
|
||||
without sending a close. If you use `0`, the session expires at the next
|
||||
evaluation; zero does not disable expiry.
|
||||
|
||||
### `--max-duration DURATION`
|
||||
|
||||
Maximum test duration a session may negotiate. A longer request is reduced
|
||||
to it, and a continuous request is answered with it. Omit this flag for no
|
||||
maximum; a maximum of zero cannot be expressed, because a negotiated
|
||||
duration of zero means continuous.
|
||||
Set the maximum test duration a session may negotiate. The server reduces
|
||||
longer requests to this value and uses it for continuous requests too.
|
||||
Leave the flag out if you don't want a maximum. You cannot set a maximum of
|
||||
zero, since a negotiated duration of zero means continuous.
|
||||
|
||||
### `--timestamp-allowance MODE`
|
||||
|
||||
@@ -147,13 +148,12 @@ and they are sent unmarked. The session is not refused.
|
||||
Durations everywhere in this command accept an integer followed by a unit:
|
||||
`ms`, `s`, or `m`.
|
||||
|
||||
## ENVIRONMENT
|
||||
## Environment
|
||||
|
||||
Every option above can also be supplied through an environment variable, for
|
||||
deployments that configure by environment rather than by command line
|
||||
(containers, orchestrators, unit files). A flag given on the command line
|
||||
overrides the corresponding variable entirely; an unset variable leaves the
|
||||
built-in default in place.
|
||||
You can also set each option through an environment variable, which is
|
||||
useful for containers, orchestrators, and unit files. A command-line flag
|
||||
overrides the corresponding variable entirely. If neither is set, the
|
||||
server uses its built-in default.
|
||||
|
||||
| Variable | Option |
|
||||
| --- | --- |
|
||||
@@ -176,10 +176,10 @@ more than one address needs repeated `--bind` options.
|
||||
an empty value leave traffic-class marking enabled; any other value disables
|
||||
it, and an unset variable leaves it enabled.
|
||||
|
||||
## OUTPUT
|
||||
## Output
|
||||
|
||||
Each bound endpoint is printed on startup, once every listener is up, which
|
||||
also resolves a port of `0`:
|
||||
Once every listener is up, the server prints each bound endpoint. If you
|
||||
requested port `0`, this shows which port was assigned:
|
||||
|
||||
```
|
||||
irtt-server: listening on [::]:2112
|
||||
@@ -188,21 +188,22 @@ irtt-server: listening on 0.0.0.0:2112
|
||||
|
||||
`Ctrl-C` stops the server gracefully.
|
||||
|
||||
## MULTIPLE LISTENERS
|
||||
## Multiple listeners
|
||||
|
||||
Every invocation runs through the same multi-listener path, so one address —
|
||||
whether from the default pair or a single explicit `--bind` — is an ordinary
|
||||
set of one rather than a separate mode. The policy options above apply to
|
||||
every listener, but listeners are otherwise independent: each has its own
|
||||
sessions and tokens, and `--max-sessions` bounds each listener rather than
|
||||
the process. If any listener fails while running, the others are shut down
|
||||
with it rather than leaving a service configured for two families answering
|
||||
on one.
|
||||
The server manages listeners the same way whether you have one or several,
|
||||
including when only one address from the default pair is available or you
|
||||
supply a single `--bind`. Each listener uses the same policy options, but
|
||||
keeps its own sessions and tokens. The `--max-sessions` limit applies to
|
||||
each listener separately.
|
||||
|
||||
If any listener fails while running, the server shuts down the others too.
|
||||
So a service configured for both address families won't carry on answering
|
||||
on just one after a listener failure.
|
||||
|
||||
Wildcard IPv4 and IPv6 listeners may share one port, as the default pair
|
||||
does.
|
||||
|
||||
## SERVER FILL
|
||||
## Server fill
|
||||
|
||||
Echo replies fill their payload according to the negotiated `ServerFill`
|
||||
mode, which a client requests with `irtt-client`'s `--sfill` (see
|
||||
@@ -212,11 +213,11 @@ mode, which a client requests with `irtt-client`'s `--sfill` (see
|
||||
- `rand`: random bytes.
|
||||
- `pattern:HEX`: the given repeating hexadecimal pattern.
|
||||
|
||||
Every valid descriptor is honored. A descriptor the server cannot parse, and
|
||||
a client that expresses no fill preference at all, both get the default
|
||||
`pattern:69727474`, i.e. the repeating bytes `69 72 74 74` (`irtt`).
|
||||
The server honors every valid descriptor. If it cannot parse the descriptor,
|
||||
or the client sends no fill preference, it uses `pattern:69727474`: the
|
||||
repeating bytes `69 72 74 74` (`irtt`).
|
||||
|
||||
## WILDCARD BINDS
|
||||
## Wildcard binds
|
||||
|
||||
An explicit interface address works on every supported system. A wildcard
|
||||
bind such as `0.0.0.0:2112` or `[::]:2112` reads each request's local
|
||||
@@ -224,14 +225,13 @@ destination from packet metadata and sends that request's reply from the
|
||||
same address, so a client on a multi-homed host is answered from the
|
||||
endpoint it actually contacted.
|
||||
|
||||
That reply-source selection is implemented on **Linux, macOS, and FreeBSD**.
|
||||
Elsewhere, a wildcard bind is refused at construction rather than served
|
||||
from a routing-table-selected source address a client would discard — this
|
||||
also applies to the zero-argument default, which will fail with a clear
|
||||
error asking for an explicit `--bind` on such a platform. This correctness
|
||||
rule is deliberate and is not weakened by the zero-argument default.
|
||||
Reply-source selection is supported on Linux, macOS, and FreeBSD. On other
|
||||
platforms, the server refuses wildcard binds because the routing table
|
||||
could select a source address the client would discard. This also means
|
||||
running without arguments fails on those platforms, with an error asking
|
||||
you to supply an explicit `--bind`.
|
||||
|
||||
## EXAMPLES
|
||||
## Examples
|
||||
|
||||
Run with the default wildcard listeners on the standard port:
|
||||
|
||||
@@ -283,19 +283,19 @@ Require authentication:
|
||||
irtt-server --bind 192.0.2.10:2112 --hmac secret
|
||||
```
|
||||
|
||||
## EXIT STATUS
|
||||
## Exit status
|
||||
|
||||
`0` on a clean shutdown (`Ctrl-C`), nonzero if binding fails or a listener
|
||||
fails while running.
|
||||
|
||||
## LIMITATIONS
|
||||
## Limitations
|
||||
|
||||
- No hostname resolution, interface expansion, daemonization, or
|
||||
configuration file — binds are explicit addresses only.
|
||||
configuration file. Binds must use explicit addresses.
|
||||
- Wildcard reply-source selection is unavailable outside Linux, macOS, and
|
||||
FreeBSD; such platforms must bind explicit addresses.
|
||||
|
||||
## SEE ALSO
|
||||
## See also
|
||||
|
||||
`irtt-client(1)`, `irtt-tui(1)`, `irtt-rs(1)`, and `irtt-server --help` for
|
||||
the full option list.
|
||||
Reference in new issue
Block a user