mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-04 06:21:15 +02:00
feat(iol): anchor IOL runner containers on persistent TAPs
IOL runner containers (IOLDockerVM, GNS3_IOL_RUNNER) had no kernel datapath: their guest leg is the runner's AF_UNIX socket pairs, so every link rode the uBridge relay. Their Ethernet bays now own persistent TAP anchors (gx names, the iol_docker key of the shared naming contract — born at node start like IOU's, before any link, so the switch fast path's deferred join can never miss them), and the per-port bridge's topology leg swaps between UDP (relay) and the anchor (kernel link) through the frozen stop -> delete -> add -> start contract — the unix binding never re-binds across a swap. - iol_docker_vm: KernelDatapathMixin hooks, the anchor lifecycle (_prepare_tap_datapath at _start_ubridge: probe ubridge_bridge_tap + ubridge_tap, sweep leftover, tap create born down), the kernel attach (ensure-then-add — tap create is strictly create-only, IFF_TUN_EXCL, so the ensure checks /sys/class/net first: an unconditional create answers EBUSY on the device the start loop just made), the release (port bridge stop + delete_nio_tap before the shared teardown) and the stop order the fd holders dictate (port bridges first, then tap delete, then the per-link bridges — all before the hypervisor stops). - vendor_docker_vm: the port-bridge creation factored into _ensure_unix_port_bridge (idempotent on the registered name), keeping the NIOBridge rejection for the generic unix-socket containers. - docker_vm: the three _kernel_veths lookups go through the _kernel_host_ifc hook — behavior-identical for DockerVM, and it is what lets the subclass route without overriding the binding methods. - kernel_anchor: the iol_docker key (gx) and kernel_anchor_type, the controller-side mapping for naming an IOL runner's anchor on the switch fast path (the marker check stays inline: this module sits below everything and must not import the controller package).
This commit is contained in:
7 files changed
+773
-31
No files matched your search
@@ -395,7 +395,28 @@ class VendorDockerVM(DockerVM):
|
||||
Override: with GNS3_UNIX_SOCKET_NIO, bridge the adapter port through
|
||||
the image's AF_UNIX datagram socket pair (raw Ethernet frames)
|
||||
instead of a TAP interface moved into the container's network
|
||||
namespace.
|
||||
namespace — see ``_ensure_unix_port_bridge`` for the wiring.
|
||||
"""
|
||||
|
||||
if not self._unix_socket_nio:
|
||||
return await super()._add_ubridge_connection(nio, adapter_number, port_number)
|
||||
|
||||
if isinstance(nio, NIOBridge):
|
||||
raise DockerError(
|
||||
f"Container '{self._name}' bridges its adapters through AF_UNIX sockets; "
|
||||
"kernel-datapath links are not supported for this container"
|
||||
)
|
||||
|
||||
await self._ensure_unix_port_bridge(adapter_number, port_number)
|
||||
|
||||
if nio:
|
||||
await self._connect_nio(adapter_number, nio, port_number)
|
||||
|
||||
async def _ensure_unix_port_bridge(self, adapter_number, port_number):
|
||||
"""
|
||||
The adapter port's uBridge bridge with its unix-socket NIO — the
|
||||
guest leg every link topology rides on. Idempotent: an already
|
||||
created bridge (this start wired it) is left alone.
|
||||
|
||||
Ports are addressed flat across adapters: interface index = adapter
|
||||
number × ports-per-adapter + port number (single-port adapters
|
||||
@@ -413,15 +434,6 @@ class VendorDockerVM(DockerVM):
|
||||
uses.
|
||||
"""
|
||||
|
||||
if not self._unix_socket_nio:
|
||||
return await super()._add_ubridge_connection(nio, adapter_number, port_number)
|
||||
|
||||
if isinstance(nio, NIOBridge):
|
||||
raise DockerError(
|
||||
f"Container '{self._name}' bridges its adapters through AF_UNIX sockets; "
|
||||
"kernel-datapath links are not supported for this container"
|
||||
)
|
||||
|
||||
try:
|
||||
adapter = self._ethernet_adapters[adapter_number]
|
||||
except IndexError:
|
||||
@@ -429,6 +441,8 @@ class VendorDockerVM(DockerVM):
|
||||
|
||||
interface_number = adapter_number * adapter.interfaces + port_number
|
||||
bridge_name = self._bridge_name(adapter_number, port_number)
|
||||
if bridge_name in self._bridges:
|
||||
return
|
||||
try:
|
||||
await self._ubridge_send(f"bridge create {bridge_name}")
|
||||
self._bridges.add(bridge_name)
|
||||
@@ -470,9 +484,6 @@ class VendorDockerVM(DockerVM):
|
||||
remote_sock,
|
||||
)
|
||||
|
||||
if nio:
|
||||
await self._connect_nio(adapter_number, nio, port_number)
|
||||
|
||||
async def _set_adapter_carrier(self, adapter_number, connected, port_number=0):
|
||||
"""
|
||||
Override: with GNS3_UNIX_SOCKET_NIO the bridges carry only unix and
|
||||
|
||||
Reference in new issue
Block a user