mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
fix: UDP port allocation race causing link self-loop (one-way links)
PortManager.get_free_udp_port had an unguarded find-then-add sequence. A link allocates both ends concurrently (asyncio.gather in UDPLink._prepare -> two POST /ports/udp) and FastAPI runs the sync route handler in a threadpool, so both threads could probe the same 'free' port before either recorded it — handing lport == rport to both ends. uBridge sets SO_REUSEADDR on UDP NIO sockets, so the double bind succeeds silently and the kernel delivers everything to the last-bound socket: one node starves, the other echoes to itself. Make every TCP/UDP allocate/reserve/release path atomic with an RLock, and rebuild _link_data in UDPLink._prepare so reset() commits the fresh port pair instead of re-sending the stale, already-released one. Regression tests: threaded barrier allocation never returns duplicates (red on the old code, UDP and TCP); reset() leaves exactly one mirrored NIO pair per side with lport != rport (red on the old code).
This commit is contained in:
7 files changed
+285
-89
No files matched your search
@@ -98,6 +98,13 @@ class UDPLink(Link):
|
||||
tuples, ready to be POSTed to each node's compute.
|
||||
"""
|
||||
|
||||
# Start from a clean slate: reset() re-creates the link on the same
|
||||
# object (delete() + create()), and _commit_nios()/update() always
|
||||
# address indices 0/1 — appending onto the previous run's entries
|
||||
# would re-commit the stale (already released) port pair and orphan
|
||||
# the freshly allocated ports.
|
||||
self._link_data = []
|
||||
|
||||
node1 = self._nodes[0]["node"]
|
||||
adapter_number1 = self._nodes[0]["adapter_number"]
|
||||
port_number1 = self._nodes[0]["port_number"]
|
||||
|
||||
Reference in new issue
Block a user