Follow-up enrichments to the Per-filter guide, one per filter, each
answering the question a reader asks right after "what does it do":
- window_drop: explicit recurrence formula ([Start + k*Period, +Outage),
duty cycle) and ASCII timelines of the three forms (one-shot /
recurring / jittered); Chance spelled out as an independent per-packet
draw gated to the window; jitter explained as per-cycle re-draws that
break phase-locking with protocol timers
- quota: transparent until the budget is consumed; Chance equals
packet_loss in draw mathematics but runs in the eBPF classifier stage
(no correlation parameter, outside seed, invisible to captures)
- limit: the phantom-loss symptom (throughput below the configured rate
with rate+delay set = the 1000 default overflowing)
- seed: reproduction also requires the same traffic pattern (draws are
consumed per arriving packet); one pinned realization is not the
distribution — statistical conclusions need several seeds
- gemodel: scattered-vs-bursty timeline at the same 5% mean (fast
retransmit vs RTO), and a parameter recipe (M and L -> r, p)
- reorder: the mechanism is queue-jumping on the netem delay queue —
hence the delay requirement, the limit overflow interaction and the
delay-bounded reorder depth
- rate: per-direction independent shaping (symmetric full duplex, no
shared budget); asymmetric rates need in-guest netem
- duplicate: real-world prototype (802.11 ARQ retransmissions), example
values with the correlation-collapse anchors (10/25 -> ~1.8%, 25/25
-> ~16.7%)
Make the feature doc usable as a standalone reference:
- Parameter reference: all 13 filters' parameters, ranges and units, the
cross-filter rules (reorder+delay, gemodel/packet_loss exclusivity,
period>=outage, distribution needs jitter), the zero-means-disabled
convention, and the UI display names served by available_filters
(the Web UI labels gemodel as "Gilbert-Elliot loss", never by type)
- Per-filter guide: purpose, per-parameter meaning, caveats and a copyable
example for each of the 13 types, including the four jitter
distributions compared (uniform/normal/pareto/paretonormal)
- REST surface: endpoint table with privileges, a filters PUT example,
and common recipes (WAN latency, bursty loss via gemodel, rate cap,
ICMP blackhole, scheduled outage)
- Clarify gemodel's "one-way" mean: per direction, independent instances
per endpoint, round trip compounds to 1-(1-mean)^2; one-directional
loss is not expressible through the link filters dict
- Fix an inaccuracy: available_filters is a dedicated endpoint's response,
not a field of the link payload
The kernel's correlated-random generator (get_crandom, sch_netem.c) truncates
instead of wrapping, starving both edges of the stationary distribution: an
event threshold below the correlation value is almost never reached. Measured
with stock iproute2 on this kernel — uBridge's netlink encoding is identical:
loss 1% + correl 25% drops nothing over 2000 pings (expected ~2%), 10%/25%
measures ~1.8% one way, only the 50% symmetry point survives. duplicate and
reorder correl share the same comparison structure and collapse the same way;
gemodel is immune (Markov chain over plain uniform draws) and is the honest
tool for bursty loss at a chosen mean rate.
Documented in the packet-filters correlation-bias bullet, and surfaced in the
two machine-facing descriptions (MCP link_update packet_loss note, controller
filter schema) so agents and clients stop walking into the trap.
A "Combining filters" section for packet-filters.md: deterministic drops
are an OR-gate (first kill wins — a clsact-dropped frame consumes no rate
serialization, no limit capacity and no netem counter), netem draws are
independent probabilities that multiply in one qdisc pass, and a round
trip squares everything. The couplings that do exist: quota's byte count
sees only frequency_drop survivors (ordered evaluation slows the burn),
delay/reorder/rate fold into one time_to_send, limit x rate x delay is
the tail-drop triangle to watch, and seed pins netem's draws but not the
eBPF program's own PRNG. Closes with a fully-loaded 12-filter walkthrough
of one frame through the gauntlet.
The Packet filters section of docker-kernel-datapath.md was the de-facto
filter documentation every other datapath doc pointed at; move it to
features/packet-filters.md as the node-type-neutral home (veth or TAP
anchor), centered on a mermaid walkthrough of all 13 types through the
anchor's egress chain: clsact first (the eBPF stateful classifier's nth /
quota / window modes at prio 1, then the bpf expression lines at 10-99,
first drop wins), the single netem qdisc behind it (enqueue draws, one
time_to_send drained by the delay queue).
Clarify a naming trap the table verbs invite: uBridge's tc module only
borrows the iproute2 vocabulary — the tc ... tokens are its own hypervisor
command names over hand-built netlink messages (RTM_NEWQDISC /
RTM_NEWTFILTER), raw bpf() syscalls, embedded distribution tables and
instruction array, libpcap as a library only; the tc binary is never
invoked outside the test suite's oracles. Verified against the uBridge
sources (hypervisor_tc.c, tc_impair.bpf.c, tc_ebpf.c), not just the
commands gns3-server sends.
docker-kernel-datapath.md keeps a pointer section; the iol doc's filter
reference and docs/README.md's tree and catalog point at the new doc.