mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-10-18 00:50:09 +03:00
Cross-compute links can ride kernel VXLAN tunnels instead of the uBridge
UDP relay: each endpoint creates one VXLAN device (uBridge's rtnetlink
vxlan module) enslaved into the same per-link Linux bridge the same-host
datapath uses, so filters, markers, capture and suspend keep running on
the anchor unchanged. Opt-in (Server.enable_vxlan_cross_compute, default
off) because the tunnel caps the usable MTU at the underlay minus the
outer headers; the relay stays the default and the fallback.
The controller derives what the pair must agree on: one VNI per link
(upper VNI space, per-link random salt) and deterministic device names
(gvl{link}{node}) that make crashed-run leftovers claimable
(show -> delete -> create). Same-host compute pairs, switch endpoints
and serial/unix-socket containers stay on the relay.
A VNI the kernel refuses self-heals on every path it can surface:
interactive create retries a fresh salt then degrades to the relay;
project open re-dispatches refused batch entries the same way; node
start recognises the refused device, stops the half-started node,
re-wires both ends on a fresh VNI (or degrades the link) and retries
the start. The device MTU is derived from the lower device (dev=) and
the per-link bridge inherits it - no configuration. The capability
probe (ubridge_vxlan in /capabilities) runs one scratch create/delete
on a scratch port that never equals the configured dstport.
The e2e scenario runs two computes on one machine (a network namespace
joined by a veth pair as the fabric) and needs root.
99 lines
3.3 KiB
Python
99 lines
3.3 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 on the veth host end — one tc netem qdisc
|
|
(delay/loss/corrupt and the netem extensions), cls_bpf match-drop (bpf) and
|
|
the eBPF stateful classifier (frequency_drop, quota, window_drop); markers
|
|
and packet capture are served by uBridge's AF_PACKET modules on the
|
|
veth host end (marker add_kernel / capture start_kernel).
|
|
|
|
``bridge`` may be ``None``: the anchor is then bridged elsewhere — an
|
|
Ethernet switch absorbed it into the switch's own kernel bridge — and this
|
|
node applies only the link state the anchor carries (carrier, markers,
|
|
impairments), never bridge membership.
|
|
|
|
A NIO may additionally carry ``vxlan`` (a BridgeVxlan spec): the link
|
|
crosses computes through a VXLAN device this end creates (uBridge's
|
|
``vxlan`` module) and enslaves into the same per-link bridge next to the
|
|
anchor. The kernel encapsulates/decapsulates the frames; everything else —
|
|
filters, markers, capture, carrier, suspend — still runs on the anchor, so
|
|
the datapath behaves exactly like a same-host kernel link.
|
|
"""
|
|
|
|
from .nio import NIO
|
|
|
|
|
|
class NIOBridge(NIO):
|
|
"""
|
|
Kernel-bridge NIO.
|
|
|
|
:param bridge: name of the per-link Linux kernel bridge, or None when
|
|
the anchor is bridged by an Ethernet switch (see module docstring)
|
|
:param vxlan: cross-compute tunnel spec (dict: name/vni/remote/dstport)
|
|
this end creates and enslaves into the bridge, or None for a
|
|
same-host kernel link
|
|
"""
|
|
|
|
def __init__(self, bridge, vxlan=None):
|
|
|
|
super().__init__()
|
|
self._bridge = bridge
|
|
self._vxlan = vxlan
|
|
|
|
@property
|
|
def bridge(self):
|
|
"""
|
|
Returns the kernel bridge name, or None for an externally bridged
|
|
anchor.
|
|
|
|
:returns: bridge name
|
|
"""
|
|
|
|
return self._bridge
|
|
|
|
@property
|
|
def vxlan(self):
|
|
"""
|
|
Returns the cross-compute VXLAN tunnel spec, or None when the link
|
|
is wired on this host alone.
|
|
|
|
:returns: dict (name/vni/remote/dstport) or None
|
|
"""
|
|
|
|
return self._vxlan
|
|
|
|
def __str__(self):
|
|
|
|
return "NIO bridge"
|
|
|
|
def asdict(self):
|
|
|
|
return {
|
|
"type": "nio_bridge",
|
|
"bridge": self._bridge,
|
|
"vxlan": self._vxlan,
|
|
"suspend": self._suspended,
|
|
"filters": self._filters,
|
|
"markers": self._markers,
|
|
}
|