Merge pull request #3031 from yueguobin/docs/netem-seed-kernel-requirement

docs: state the Linux 6.6 requirement of the netem seed filter
This commit is contained in:
Jeremy Grossmann 2026-10-26 08:02:53 +01:00 committed by GitHub
commit ac01ee6190
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 15 additions and 7 deletions

View File

@ -142,8 +142,14 @@ direction, `loss gemodel 5 45 100` drops 10 %.
(normal / pareto / paretonormal — same values iproute2 ships as (normal / pareto / paretonormal — same values iproute2 ships as
`*.dist`, generated by netem's `maketable`) as const arrays in uBridge; `*.dist`, generated by netem's `maketable`) as const arrays in uBridge;
select by name. Without DIST the kernel silently uses uniform jitter. select by name. Without DIST the kernel silently uses uniform jitter.
* seed: `TCA_NETEM_SEED` (u64 allowed) — makes random draws reproducible * seed: `TCA_NETEM_PRNG_SEED` (u64; uapi slot 14, introduced in Linux 6.6)
for tests. When omitted keep the current behaviour (kernel picks). — makes random draws reproducible for tests. When omitted keep the
current behaviour (kernel picks). Pre-6.6 kernels parse the qdisc
options non-strictly and silently drop the attribute: determinism is
unavailable there while every other knob still applies. A build against
pre-6.6 `linux/pkt_sched.h` must define the constant behind a
`LINUX_VERSION_CODE` guard (enum constants are invisible to the
preprocessor, so `#ifndef` cannot detect them).
### A.3 Reply contract (unchanged shape) ### A.3 Reply contract (unchanged shape)

View File

@ -76,7 +76,7 @@ On the kernel datapath the 13 types ride three kernel objects on the anchor. The
| `rate ["512kbit"]` | netem `rate B` | tc-style integer+unit (bit/kbit/mbit/gbit/bps/kbps/mbps, ≤100gbit); kernel-only type | | `rate ["512kbit"]` | netem `rate B` | tc-style integer+unit (bit/kbit/mbit/gbit/bps/kbps/mbps, ≤100gbit); kernel-only type |
| `reorder [%, correl, gap]` | netem `reorder P [correl C] [gap G]` | requires `delay`; kernel-only type | | `reorder [%, correl, gap]` | netem `reorder P [correl C] [gap G]` | requires `delay`; kernel-only type |
| `gemodel [p, r, 1-h]` | netem `loss gemodel P R H` | Gilbert-Elliot bursty loss: p = good→bad transition, r = bad→good transition, 1-h = loss chance in the bad state (good loses nothing) — mean one-way loss p/(p+r)×(1-h); mutually exclusive with `packet_loss`; kernel-only type | | `gemodel [p, r, 1-h]` | netem `loss gemodel P R H` | Gilbert-Elliot bursty loss: p = good→bad transition, r = bad→good transition, 1-h = loss chance in the bad state (good loses nothing) — mean one-way loss p/(p+r)×(1-h); mutually exclusive with `packet_loss`; kernel-only type |
| `seed [u32]` | netem `seed N` | reproducible random draws; kernel-only type | | `seed [u32]` | netem `seed N` | reproducible random draws; kernel-only type — seeded draws need Linux ≥ 6.6, older kernels silently ignore the seed (every other knob applies) |
| `limit [pkts]` | netem `limit N` | queue depth above the 1000 default (rate+delay BDP); kernel-only type | | `limit [pkts]` | netem `limit N` | queue depth above the 1000 default (rate+delay BDP); kernel-only type |
| `bpf` (one line per expression, OR) | `tc bpf_drop add <if> <prio> "<expr>"` — cls_bpf on clsact egress + gact drop | needs uBridge `cbpf=1` (`tc capabilities`, probed once per uBridge process); a line that fails to compile on the compute is skipped with a warning, mirroring the relay | | `bpf` (one line per expression, OR) | `tc bpf_drop add <if> <prio> "<expr>"` — cls_bpf on clsact egress + gact drop | needs uBridge `cbpf=1` (`tc capabilities`, probed once per uBridge process); a line that fails to compile on the compute is skipped with a warning, mirroring the relay |
| `frequency_drop [N]` | `tc nth_drop <if> N` — the eBPF stateful classifier's exact every-Nth mode (clsact egress prio 1) | needs uBridge `ebpf=1`; -1 = drop everything → every 1st; per-direction counters (see below) | | `frequency_drop [N]` | `tc nth_drop <if> N` — the eBPF stateful classifier's exact every-Nth mode (clsact egress prio 1) | needs uBridge `ebpf=1`; -1 = drop everything → every 1st; per-direction counters (see below) |
@ -96,7 +96,7 @@ The API surface of the 13 types — parameters, ranges and cross-filter rules, v
| `rate` **K** | Bandwidth limit | Rate — tc-style string, e.g. `"512kbit"` (≤ 100gbit) | integer + unit; bps-family units count bytes/s | | `rate` **K** | Bandwidth limit | Rate — tc-style string, e.g. `"512kbit"` (≤ 100gbit) | integer + unit; bps-family units count bytes/s |
| `reorder` **K** | Reorder | Reorder (0…100 %) · Correlation (0…100 %) · Gap (1…1000 packets) | requires `delay` | | `reorder` **K** | Reorder | Reorder (0…100 %) · Correlation (0…100 %) · Gap (1…1000 packets) | requires `delay` |
| `gemodel` **K** | Gilbert-Elliot loss | p (good-to-bad) · r (bad-to-good) · 1-h (bad-state loss) (each 0…100 %) | mutually exclusive with `packet_loss` | | `gemodel` **K** | Gilbert-Elliot loss | p (good-to-bad) · r (bad-to-good) · 1-h (bad-state loss) (each 0…100 %) | mutually exclusive with `packet_loss` |
| `seed` **K** | Random seed | Seed (0…4294967295) | pins the netem draws only | | `seed` **K** | Random seed | Seed (0…4294967295) | pins the netem draws only; reproducibility needs Linux ≥ 6.6 |
| `limit` **K** | Queue limit | Limit (1…1000000 packets) | queue depth above the 1000 default | | `limit` **K** | Queue limit | Limit (1…1000000 packets) | queue depth above the 1000 default |
| `bpf` | Berkeley Packet Filter (BPF) | Filters — text, one expression per line | any match drops | | `bpf` | Berkeley Packet Filter (BPF) | Filters — text, one expression per line | any match drops |
| `frequency_drop` | Frequency drop | Frequency (−1…32767) | −1 drops everything; 0 disables | | `frequency_drop` | Frequency drop | Frequency (−1…32767) | −1 drops everything; 0 disables |
@ -229,7 +229,7 @@ Choosing parameters: pick the target mean M and average burst length L (packets)
|---|---| |---|---|
| Seed (0…4294967295) | the netem PRNG seed | | Seed (0…4294967295) | the netem PRNG seed |
**Note**: pins the netem draws only — the eBPF percentage draws (quota, window) ride a PRNG seeded at program load, outside `seed`'s reach; any filter-set change resets schedules and counters. Two more boundaries: reproduction also requires the same traffic pattern (draws are consumed per arriving packet — classifier-stage drops upstream change the sequence), and a fixed seed pins one realization, not the distribution — for statistical conclusions (average throughput under loss) run several seeds. **Note**: pins the netem draws only — the eBPF percentage draws (quota, window) ride a PRNG seeded at program load, outside `seed`'s reach; any filter-set change resets schedules and counters. Two more boundaries: reproduction also requires the same traffic pattern (draws are consumed per arriving packet — classifier-stage drops upstream change the sequence), and a fixed seed pins one realization, not the distribution — for statistical conclusions (average throughput under loss) run several seeds. One more: the seeded PRNG itself is a Linux 6.6 addition — on older kernels the seed attribute is silently ignored (no error), the draws stay random while every other netem knob applies.
**Example**: `{"packet_loss": [10], "seed": [42]}`. **Example**: `{"packet_loss": [10], "seed": [42]}`.

View File

@ -133,7 +133,8 @@ class GNS3PacketFilterTool(BaseTool):
- "gemodel": Gilbert-Elliot bursty loss (parameters: p good-to-bad transition, r bad-to-good - "gemodel": Gilbert-Elliot bursty loss (parameters: p good-to-bad transition, r bad-to-good
transition, 1-h loss in the bad state; mean loss = p/(p+r)*(1-h); kernel links only) transition, 1-h loss in the bad state; mean loss = p/(p+r)*(1-h); kernel links only)
- "duplicate": Packet duplication percentage (kernel links only) - "duplicate": Packet duplication percentage (kernel links only)
- "seed": Reproducible netem random draws (kernel links only) - "seed": Reproducible netem random draws (kernel links only; needs kernel >= 6.6 -
older kernels silently ignore the seed)
- "limit": Impairment queue depth in packets (kernel links only) - "limit": Impairment queue depth in packets (kernel links only)
- "quota": Byte cap — after the quota, drop with a chance (parameters: bytes, chance; - "quota": Byte cap — after the quota, drop with a chance (parameters: bytes, chance;
kernel links only) kernel links only)

View File

@ -829,7 +829,8 @@ async def link_update(
steady-state mean loss = p/(p+r)*(1-h) per direction; mutually steady-state mean loss = p/(p+r)*(1-h) per direction; mutually
exclusive with packet_loss exclusive with packet_loss
* duplicate (K): [pct, correl?] - Duplication percentage * duplicate (K): [pct, correl?] - Duplication percentage
* seed (K): [u32] - Makes netem random draws reproducible * seed (K): [u32] - Makes netem random draws reproducible (needs
kernel >= 6.6; older kernels silently ignore the seed)
* limit (K): [pkts] - Impairment queue depth (default 1000; raise for * limit (K): [pkts] - Impairment queue depth (default 1000; raise for
low rate + long delay) low rate + long delay)
* quota (K): [bytes, pct] - After the byte quota is consumed, each * quota (K): [bytes, pct] - After the byte quota is consumed, each