mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 14:01:15 +02:00
controller: allow markers and packet filters on Ethernet switch links
The brctl Ethernet switch runs a per-port uBridge relay, so it can host the mark filter and packet filters like any uBridge-backed node. Add ethernet_switch to _MARKER_CAPABLE_TYPES and _get_filter_node, narrow the UDPLink.update() NIO-PUT skip down to the Dynamips-hosted ethernet_hub, and expose the matching compute endpoints: PUT nio (filter/marker reapply) plus the per-marker toggle/pause/resume/delete/rebuild routes. The ethernet_hub keeps its exclusion: its routes still wire into the Dynamips hub, which has no uBridge of its own.
This commit is contained in:
9 files changed
+282
-17
No files matched your search
@@ -378,9 +378,9 @@ async def test_available_filters(project, compute):
|
||||
link.create = AsyncioMagicMock()
|
||||
assert link.available_filters() == []
|
||||
|
||||
# Ethernet switch is not supported should return 0 filters
|
||||
# The brctl Ethernet switch hosts filters on its per-port uBridge relays
|
||||
await link.add_node(node1, 0, 4)
|
||||
assert link.available_filters() == []
|
||||
assert len(link.available_filters()) > 0
|
||||
|
||||
node2 = Node(project, compute, "node2", node_type="vpcs")
|
||||
node2._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
|
||||
@@ -56,20 +56,21 @@ def _valid_bpf():
|
||||
return stack
|
||||
|
||||
|
||||
async def _make_link(project, port_cls=EthernetPort):
|
||||
"""Build a created UDPLink between two VPCS nodes on a mocked compute.
|
||||
async def _make_link(project, port_cls=EthernetPort, node_types=("vpcs", "vpcs")):
|
||||
"""Build a created UDPLink between two nodes on a mocked compute.
|
||||
|
||||
``port_cls`` defaults to EthernetPort; pass SerialPort for a serial link
|
||||
(the link's link_type follows the port).
|
||||
(the link's link_type follows the port). ``node_types`` overrides the
|
||||
endpoint node types (e.g. a switch-to-switch link).
|
||||
"""
|
||||
|
||||
compute = MagicMock()
|
||||
compute.id = "local"
|
||||
compute.host = "example.com"
|
||||
|
||||
node1 = Node(project, compute, "n1", node_type="vpcs")
|
||||
node1 = Node(project, compute, "n1", node_type=node_types[0])
|
||||
node1._ports = [port_cls("E0", 0, 0, 0)]
|
||||
node2 = Node(project, compute, "n2", node_type="vpcs")
|
||||
node2 = Node(project, compute, "n2", node_type=node_types[1])
|
||||
node2._ports = [port_cls("E0", 0, 0, 1)]
|
||||
|
||||
async def subnet(_other):
|
||||
@@ -112,6 +113,23 @@ async def test_start_marker_stores_entry(project):
|
||||
assert entry["highlight_duration"] == 800
|
||||
assert entry["enabled"] is True
|
||||
assert entry["capture_node_id"] in {n["node"].id for n in link._nodes}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_start_marker_on_ethernet_switch_link(project):
|
||||
"""A switch-to-switch link can host a marker: the brctl Ethernet switch
|
||||
runs a per-port uBridge relay the `mark` filter attaches to."""
|
||||
|
||||
with _valid_bpf():
|
||||
link = await _make_link(project, node_types=("ethernet_switch", "ethernet_switch"))
|
||||
await link.start_marker("icmp", "icmp")
|
||||
|
||||
entry = link.markers["icmp"]
|
||||
switch_ids = {n["node"].id for n in link._nodes}
|
||||
assert entry["capture_node_id"] in switch_ids
|
||||
# the marker rides exactly one side's NIO and is pushed via update()
|
||||
carrying = [d for d in link._link_data if "icmp" in d["markers"]]
|
||||
assert len(carrying) == 1
|
||||
assert "inherited_from" not in entry
|
||||
|
||||
|
||||
|
||||
@@ -451,6 +451,55 @@ async def test_update(project):
|
||||
}, timeout=120)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_ethernet_switch_nio(project):
|
||||
"""
|
||||
Link updates must reach an Ethernet switch endpoint: the brctl switch has
|
||||
a PUT NIO route, so only the Dynamips-hosted hub side stays skipped.
|
||||
"""
|
||||
|
||||
compute1 = MagicMock()
|
||||
|
||||
node_vpcs = Node(project, compute1, "node1", node_type="vpcs")
|
||||
node_vpcs._ports = [EthernetPort("E0", 0, 0, 4)]
|
||||
node_switch = Node(project, compute1, "node2", node_type="ethernet_switch")
|
||||
node_switch._ports = [EthernetPort("E0", 0, 3, 1)]
|
||||
|
||||
async def subnet_callback(compute2):
|
||||
return ("192.168.1.1", "192.168.1.2")
|
||||
|
||||
compute1.get_ip_on_same_subnet.side_effect = subnet_callback
|
||||
|
||||
async def compute1_callback(path, data={}, **kwargs):
|
||||
if "/ports/udp" in path:
|
||||
response = MagicMock()
|
||||
response.json = {"udp_port": 1024}
|
||||
return response
|
||||
|
||||
compute1.post.side_effect = compute1_callback
|
||||
compute1.put = AsyncioMagicMock()
|
||||
compute1.host = "example.com"
|
||||
|
||||
link = UDPLink(project)
|
||||
await link.add_node(node_vpcs, 0, 4)
|
||||
await link.add_node(node_switch, 3, 1)
|
||||
assert link.created
|
||||
|
||||
await link.update_filters({"delay": [10, 0]})
|
||||
compute1.put.assert_any_call(
|
||||
"/projects/{}/ethernet_switch/nodes/{}/adapters/3/ports/1/nio".format(project.id, node_switch.id),
|
||||
data={
|
||||
"lport": 1024,
|
||||
"rhost": "192.168.1.1",
|
||||
"rport": 1024,
|
||||
"type": "nio_udp",
|
||||
"suspend": False,
|
||||
"markers": {},
|
||||
"filters": {}
|
||||
}, timeout=221
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_suspend(project):
|
||||
compute1 = MagicMock()
|
||||
|
||||
Reference in new issue
Block a user