YueGuobin 0a8d430d50
feat(docker): packet filters on kernel-datapath links via tc netem
Impairment filters with a netem equivalent (delay, packet_loss, corrupt)
now run on the kernel datapath as one tc netem qdisc per veth host end,
pushed through uBridge's netlink tc module (tc netem set / tc reset).
This removes the relay delay filter's nanosleep bottleneck (upstream

Both link endpoints carry the filters: each end's qdisc egress covers
the traffic entering that container, so every direction is impaired
exactly once -- the same net effect as the relay, where both directions
cross the single filtered bridge.

- controller: eligibility keys on relay-only types (frequency_drop, bpf)
  instead of any filter; kernel links push the real filters (the
  synthetic suspend frequency_drop no longer flips a suspended link to
  relay on reopen/reset); update_filters 409s only relay-only types;
  available_filters hides them on kernel links
- compute: create_nio whitelists netem-capable filter types; the NIO
  update path keeps its own guard (PUT mutates the NIO in place);
  _ubridge_apply_netem translates the filter dict into one atomic
  netem-set (full re-apply IS the reconcile); node restart restores the
  qdisc, link deletion detaches it (the veth survives the link)
- e2e (27/27): delay 100 -> 200.2 ms RTT, atomic replace 50 -> 100.2 ms,
  clear -> baseline, packet_loss 30 -> 48 % round-trip (expected 51 %),
  suspend/resume and node restart keep the qdisc, link delete leaves no
  residual impairment
2026-10-06 00:21:08 +08:00

69 lines
1.9 KiB
Python

#
# Copyright (C) 2026 GNS3 Technologies Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Interface for kernel-datapath bridge NIOs.
A NIO of this type instructs the node to enslave its adapter's veth host end
into the named Linux kernel bridge instead of wiring a uBridge UDP relay.
Frames then flow entirely in the kernel (veth -> bridge -> veth). Impairment
filters ride the NIO and run as one tc netem qdisc per veth host end (the
types without a netem equivalent — frequency_drop, bpf — stay relay-only);
markers and packet capture are served by uBridge's AF_PACKET modules on the
veth host end (marker add_kernel / capture start_kernel).
"""
from .nio import NIO
class NIOBridge(NIO):
"""
Kernel-bridge NIO.
:param bridge: name of the per-link Linux kernel bridge
"""
def __init__(self, bridge):
super().__init__()
self._bridge = bridge
@property
def bridge(self):
"""
Returns the kernel bridge name.
:returns: bridge name
"""
return self._bridge
def __str__(self):
return "NIO bridge"
def asdict(self):
return {
"type": "nio_bridge",
"bridge": self._bridge,
"suspend": self._suspended,
"filters": self._filters,
"markers": self._markers,
}