mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-10-13 05:55:35 +03:00
feat(controller): offer Dynamips the kernel datapath
A Dynamips Ethernet port can anchor a kernel link whenever its compute's uBridge has the tap module — the anchors are uBridge-created TAPs the hypervisor merely opens, the same capability QEMU gates on, so no Dynamips-specific capability is needed. Serial, ATM and POS ports are excluded per port by the existing link-type check (the controller's port matrix decides), keeping them on the relay whatever the capabilities. Eligibility tests cover the mixed pairs (docker/qemu/iou endpoints on the same compute), the strict tap-capability requirement, and the serial exclusion.
This commit is contained in:
parent
7201a870da
commit
e5f65a510a
@ -182,9 +182,12 @@ class UDPLink(Link):
|
||||
datapath and cannot carry a kernel link at all. IOU's Ethernet
|
||||
bays anchor on persistent TAPs too, bound to its IOL fabric
|
||||
(``iol_bridge add_nio_tap``) — a separate capability, since it can
|
||||
be present or absent independently of the tap module. A kernel link
|
||||
is an Ethernet segment, so non-Ethernet ports (IOU serial) stay on
|
||||
the relay whatever the node's capabilities.
|
||||
be present or absent independently of the tap module. Dynamips
|
||||
Ethernet slot ports anchor on persistent TAPs the hypervisor opens
|
||||
(the tap module again — the Dynamips binary itself creates nothing),
|
||||
so it gates like QEMU. A kernel link is an Ethernet segment, so
|
||||
non-Ethernet ports (IOU serial, Dynamips serial/ATM/POS adapters)
|
||||
stay on the relay whatever the node's capabilities.
|
||||
"""
|
||||
|
||||
if not Config.instance().settings.Server.enable_kernel_datapath:
|
||||
@ -214,6 +217,11 @@ class UDPLink(Link):
|
||||
return capabilities.get("ubridge_tap") is True
|
||||
if node.node_type == "iou":
|
||||
return capabilities.get("ubridge_iol_tap") is True
|
||||
if node.node_type == "dynamips":
|
||||
# The anchors are uBridge-created TAPs the Dynamips hypervisor
|
||||
# merely opens (nio create_tap) — the same tap-module capability
|
||||
# QEMU needs, not a Dynamips-specific one.
|
||||
return capabilities.get("ubridge_tap") is True
|
||||
return False
|
||||
|
||||
async def _prepare(self):
|
||||
|
||||
@ -169,6 +169,70 @@ async def test_iou_eligibility_is_its_own_capability(project):
|
||||
assert link._kernel_datapath_eligible(node1, node2) is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_kernel_datapath_eligible_for_dynamips_with_tap_support(project):
|
||||
"""
|
||||
Dynamips Ethernet slot ports anchor on persistent TAPs the hypervisor
|
||||
opens (nio create_tap on a uBridge-created device), so they gate on the
|
||||
tap module like QEMU — no Dynamips-specific capability — and mix with
|
||||
docker/qemu/iou endpoints on the same compute.
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "compute-1"
|
||||
compute.capabilities = {"ubridge_tap": True, "ubridge_iol_tap": True}
|
||||
node1 = _node(project, compute, "r1", node_type="dynamips")
|
||||
node2 = _node(project, compute, "r2", node_type="dynamips")
|
||||
link = await _link(project, node1, node2)
|
||||
assert link._kernel_datapath_eligible(node1, node2) is True
|
||||
|
||||
for peer in (
|
||||
_node(project, compute, "docker1"),
|
||||
_node(project, compute, "qemu1", node_type="qemu"),
|
||||
_node(project, compute, "iou1", node_type="iou"),
|
||||
):
|
||||
link = await _link(project, node1, peer)
|
||||
assert link._kernel_datapath_eligible(node1, peer) is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dynamips_eligibility_follows_the_tap_capability(project):
|
||||
"""
|
||||
A compute whose uBridge cannot create persistent TAPs keeps Dynamips on
|
||||
the relay (the hypervisor would have nothing to open), and so does an
|
||||
unreported/failed probe.
|
||||
"""
|
||||
|
||||
node2 = _node(project, _tap_capable_compute(), "docker1")
|
||||
for tap_support in (None, False):
|
||||
compute = _tap_capable_compute(tap_support=tap_support)
|
||||
node1 = _node(project, compute, "r1", node_type="dynamips")
|
||||
link = await _link(project, node1, node2)
|
||||
assert link._kernel_datapath_eligible(node1, node2) is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_kernel_datapath_not_eligible_for_dynamips_serial_ports(project):
|
||||
"""
|
||||
A Dynamips serial port (NM-4T, WIC-2T, ...) stays on the relay whatever
|
||||
the compute's capabilities — the same per-port exclusion as IOU serial,
|
||||
decided by the controller's port matrix.
|
||||
"""
|
||||
|
||||
from gns3server.controller.ports.serial_port import SerialPort
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "compute-1"
|
||||
compute.capabilities = {"ubridge_tap": True}
|
||||
|
||||
node1 = _node(project, compute, "r1", node_type="dynamips")
|
||||
node1._ports = [SerialPort("Serial0/0", 0, 0, 0)]
|
||||
node2 = _node(project, compute, "r2", node_type="dynamips")
|
||||
node2._ports = [SerialPort("Serial0/0", 0, 0, 0)]
|
||||
link = await _link(project, node1, node2)
|
||||
assert link._kernel_datapath_eligible(node1, node2) is False
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_kernel_datapath_not_eligible_for_serial_ports(project):
|
||||
"""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user