mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 14:01:15 +02:00
feat(docker): expose netem-extension packet filters on kernel links
Surface the netem extensions delivered in uBridge feature/tc-netem-ext as GNS3 filter types: rate (tc-style bandwidth string), reorder (needs delay), gemodel (Gilbert-Elliot bursty loss, exclusive with packet_loss), duplicate, seed and limit, plus the delay jitter distribution and the loss/dup correlation parameters. All are kernel-datapath only — the relay's packet-filter registry has no equivalent, so available_filters hides them on relay links, setting one on a created relay link returns 409, and the project-load path drops them with a warning (update_filters runs before the datapath is decided, so it cannot reject there). Validation mirrors the tc grammar: reorder requires delay, gemodel and packet_loss are mutually exclusive, a distribution requires jitter > 0, rate is integer+unit capped at 100gbit. The translation in DockerVM._netem_command_parts emits the frozen grammar order and gates extension keywords on the 'tc capabilities' netem token list (probed once per uBridge process; a plain delay/loss/corrupt/dup filter never probes, keeping old uBridge builds untouched; the correl suffix has no token and gates on 'rate' as the extension-build marker). Reconcile became reset-before-set: the kernel's netem change merges optional attributes (rate, correlation, reorder, corrupt, gemodel, distribution, seed keep their previous value when the new message omits them), so removing a parameter needs an explicit 'tc reset' — the bpf_drop filters are re-added right after in the same flow, so the clsact churn is invisible. The capability check runs before the reset so a failed update leaves the previous qdisc in place. e2e (isolated instance, kernel link): 24/24 — rate 512kbit adds exactly 2x the per-packet serialization to the RTT (45.5 ms for 1400-byte pings), paretonormal jitter + rate-cleared leak check, reorder gap 5, gemodel 50% bursty loss, duplicate, loss 30% correl 50%, seed 42 + limit 5000 visible in the qdisc dump, suspend/resume and node restart keep the filters, relay link rejects rate with 409, teardown leaves no netem. Full unit suite: 1916 passed.
This commit is contained in:
13 files changed
+1012
-108
No files matched your search
@@ -4,14 +4,29 @@ See LICENSE file for licensing information.
|
||||
-->
|
||||
|
||||
> Frozen requirements spec for the **uBridge** project. Delivery status:
|
||||
> parts **A** (netem keyword extensions, uBridge `feature/tc-netem-ext`) and
|
||||
> **C + D** (cBPF match-drop, full-restore idempotent `tc reset`,
|
||||
> `tc capabilities` with `cbpf` probe — uBridge `feature/tc-bpf-drop`) are
|
||||
> **delivered and integrated** on gns3-server branch
|
||||
> `feat/docker-kernel-bpf-drop`. Part **B** (eBPF stateful classifier) is
|
||||
> still pending. The originally shipped netem surface (delay/jitter/loss/
|
||||
> dup/corrupt) exists in uBridge 1.2.3+ and is verified against gns3-server
|
||||
> branch `feat/docker-kernel-filters`.
|
||||
> parts **A** (netem keyword extensions, uBridge `feature/tc-netem-ext`), **C**
|
||||
> (cBPF match-drop) and **D + E** (full-restore idempotent `tc reset`,
|
||||
> `tc capabilities` — uBridge `feature/tc-bpf-drop`) are **delivered and
|
||||
> integrated** on gns3-server branches `feat/docker-kernel-bpf-drop` (C/D/E)
|
||||
> and `feat/docker-kernel-netem-ext` (A: rate/reorder/gemodel/duplicate/
|
||||
> seed/limit/distributions/correlation exposed as GNS3 filter types).
|
||||
> Part **B** (eBPF stateful classifier) is delivered in the uBridge
|
||||
> `feature/tc-precision` branch but **not yet consumed** by gns3-server.
|
||||
> The originally shipped netem surface (delay/jitter/loss/dup/corrupt)
|
||||
> exists in uBridge 1.2.3+ and is verified against gns3-server branch
|
||||
> `feat/docker-kernel-filters`.
|
||||
>
|
||||
> **Deviation found during integration (part A/D):** the delivered
|
||||
> `tc netem set` uses NLM_F_REPLACE, but the *kernel's* netem change merges
|
||||
> optional attributes — rate, correlation, reorder, corrupt, gemodel,
|
||||
> distribution and seed keep their previous value when the new message
|
||||
> omits them, so "netem set atomically replaces" (D's reconcile
|
||||
> assumption) does not hold for parameter *removals*. gns3-server works
|
||||
> around it by sending `tc reset` before every `netem set` (the bpf_drop
|
||||
> filters are re-added right after in the same flow, so clsact churn is
|
||||
> invisible). If uBridge later emits explicit zero/absent clears for every
|
||||
> optional attribute, the server-side reset-before-set can be dropped; the
|
||||
> two behaviours are compatible either way.
|
||||
|
||||
# uBridge kernel impairment: tc netem extensions + eBPF classifiers
|
||||
|
||||
@@ -272,11 +287,17 @@ corresponding filter types per capability.
|
||||
|
||||
## gns3-server alignment (informational — not uBridge scope)
|
||||
|
||||
* P6a types map 1:1 onto new GNS3 filter entries (rate, reorder, gemodel…),
|
||||
translated in `DockerVM._ubridge_apply_netem`.
|
||||
* `frequency_drop` / `bpf` move out of `KERNEL_UNSUPPORTED_FILTERS` once
|
||||
`tc capabilities` reports `ebpf=1` / `cbpf=1` (per-compute probe, cached);
|
||||
without the capability the link stays relay-wired exactly as today.
|
||||
* **Done** (`feat/docker-kernel-netem-ext`): the P6a types map 1:1 onto new
|
||||
GNS3 filter entries (rate, reorder, gemodel, duplicate, seed, limit, plus
|
||||
the delay `distribution` and loss/dup `correlation` parameters), translated
|
||||
in `DockerVM._ubridge_apply_netem`; extension keywords are gated on the
|
||||
`tc capabilities` netem token list (old uBridge builds are never probed
|
||||
for the original surface).
|
||||
* **Done** (`feat/docker-kernel-bpf-drop`): `bpf` runs as cBPF match-drop
|
||||
(`KERNEL_UNSUPPORTED_FILTERS` shrank to `frequency_drop`).
|
||||
* `frequency_drop` moves out of `KERNEL_UNSUPPORTED_FILTERS` once the eBPF
|
||||
classifier (part B, uBridge `feature/tc-precision`) is consumed on the
|
||||
server side, keyed on `ebpf=1` per compute.
|
||||
* Every veth end owns one qdisc + its filters: per-direction impairment is
|
||||
an architectural freebie to expose later (API `direction` field), aligned
|
||||
with marker `dir` semantics.
|
||||
Reference in new issue
Block a user