YueGuobin c343ce0b8f
feat(esw): wire peer anchors straight into the switch bridge
The Ethernet switch's kernel fast path: instead of a link crossing the
switch's per-port uBridge relay, the switch absorbs the peer's anchor into
its own kernel bridge. The peer's interface (Docker veth host end, QEMU
TAP, IOU port TAP, Dynamips port TAP) becomes the switch port, and frames
cross anchor -> switch bridge -> switch ports entirely in the kernel.

Wire format: the switch end receives nio_anchor ('join this interface to
my own bridge' — the mirror of nio_bridge), the peer end nio_bridge with a
null bridge ('your anchor is bridged elsewhere': carrier, markers and
impairments only — never bridge membership, and never a bridge delete, on
an interface this node does not own). Anchor names come from the shared
naming contract (utils.kernel_anchor), a pure function of node type, id,
adapter and port — the controller computes the peer's anchor while the
node may be stopped, which is what makes links to stopped nodes wireable.

Stopped peers defer the join; after any node of a link starts
(UDPLink.node_started) the controller re-pushes the switch NIO, and the
switch completes — or repairs, when a peer restart replaced its interface
under the same name — the join against the kernel's actual membership
instead of assuming it.

VLAN changes now edit membership in place: only the ports whose mode/VLAN
actually changed are touched, each losing exactly the previous mode's
entries the new mode does not want (the dot1q admits-all entry is one
range operation in both directions), and no port ever leaves the bridge to
change its VLANs. This replaces the old 'reset by re-enslaving' shortcut
(delif+addif on every wired port, added when the ports were the switch's
own TAPs): on absorbed anchors, re-enslaving an interface owned by another
node is where live testing watched links die — anchors occasionally lost
their bridge membership right after a ports_mapping update (later updates
then failed with delif EINVAL), reproducibly with qemu, IOU and Dynamips
peers and never with Docker's veths.

Eligibility: the switch side needs no capability of its own (its bridge
exists by construction); the peer must be able to anchor. Switch-to-switch
cascades stay on the relay — a kernel interface belongs to one bridge, and
joining two bridges needs a veth pair, deferred.

Verified live on a real server: qemu peers through four VLAN cycles with
both anchors enslaved throughout; a mixed switch (2 IOU + 2 Dynamips, four
kernel ports); Docker peers with real ICMP isolating and recovering (with
both anchors still enslaved); VPCS relay ports likewise in place.
2026-10-06 00:21:09 +08:00

326 lines
9.5 KiB
Python

#
# Copyright (C) 2020 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/>.
# General schemas
from .common import ErrorMessage
from .config import ServerConfig
from .controller.appliances import Appliance, ApplianceVersion, ApplianceVersionV8
from .controller.computes import (
AutoIdlePC,
Compute,
ComputeCreate,
ComputeDockerImage,
ComputeUpdate,
ComputeVirtualBoxVM,
ComputeVMwareVM,
)
from .controller.drawings import Drawing
from .controller.gns3vm import GNS3VM
from .controller.images import Image, ImageSyncJob, ImageSyncRequest, ImageType
# Controller schemas
from .controller.links import (
EthernetPortInfo,
Link,
LinkCapture,
LinkCreate,
LinkUpdate,
MarkerCreate,
MarkerDefinitionCreate,
MarkerUpdate,
UDPPortInfo,
)
from .controller.nodes import Node, NodeCapture, NodeCreate, NodeDuplicate, NodeUpdate
from .controller.projects import (
NodeFile,
Project,
ProjectCompression,
ProjectCreate,
ProjectDuplicate,
ProjectFile,
ProjectUpdate,
)
from .controller.templates import Template, TemplateCreate, TemplateUpdate, TemplateUsage
from .controller.users import (
Credentials,
LoggedInUserUpdate,
User,
UserCreate,
UserGroup,
UserGroupCreate,
UserGroupUpdate,
UserUpdate,
)
from .version import Version
# Conditionally import AI-related schemas
try:
from .controller.chat import (
ChatRequest,
ChatResponse,
ChatSession,
ConversationHistory,
OpenAIMessage,
OpenAIToolCall,
RenameSession,
)
from .controller.llm_model_configs import (
LLMModelConfigCreate,
LLMModelConfigData,
LLMModelConfigInheritedResponse,
LLMModelConfigListResponse,
LLMModelConfigResponse,
LLMModelConfigUpdate,
LLMModelConfigWithSource,
)
except ImportError:
# AI schemas are not available (should not happen as they don't depend on external libs)
pass
from .compute.atm_switch_nodes import ATMSwitch, ATMSwitchCreate, ATMSwitchUpdate
from .compute.cloud_nodes import Cloud, CloudCreate, CloudUpdate
from .compute.docker_nodes import Docker, DockerCreate, DockerUpdate
from .compute.dynamips_nodes import Dynamips, DynamipsCreate, DynamipsUpdate
from .compute.ethernet_hub_nodes import EthernetHub, EthernetHubCreate, EthernetHubUpdate
from .compute.ethernet_switch_nodes import EthernetSwitch, EthernetSwitchCreate, EthernetSwitchUpdate
from .compute.frame_relay_switch_nodes import FrameRelaySwitch, FrameRelaySwitchCreate, FrameRelaySwitchUpdate
from .compute.iou_nodes import IOU, IOUCreate, IOUStart, IOUUpdate
from .compute.nat_nodes import NAT, NATCreate, NATUpdate
# Compute schemas
from .compute.nios import AnchorNIO, TAPNIO, UDPNIO, BridgeNIO, BatchNIOCreate, BatchNIOEntry, EthernetNIO, MarkerRebuild, MarkerToggle
from .compute.qemu_nodes import Qemu, QemuCreate, QemuUpdate
from .compute.virtualbox_nodes import VirtualBox, VirtualBoxCreate, VirtualBoxUpdate
from .compute.vmware_nodes import VMware, VMwareCreate, VMwareUpdate
from .compute.vpcs_nodes import VPCS, VPCSCreate, VPCSUpdate
from .controller.capabilities import Capabilities
from .controller.iou_license import IOULicense
from .controller.netmiko import NetmikoDeviceType, NetmikoDeviceTypeList
from .controller.pools import Resource, ResourceCreate, ResourcePool, ResourcePoolCreate, ResourcePoolUpdate
from .controller.rbac import ACE, ACECreate, ACEUpdate, Privilege, Role, RoleCreate, RoleUpdate
from .controller.settings import SettingsResponse, SettingsUpdate, SettingsUpdateResponse
from .controller.snapshots import Snapshot, SnapshotCreate
from .controller.templates.cloud_templates import CloudTemplate, CloudTemplateUpdate
from .controller.templates.docker_templates import DockerTemplate, DockerTemplateUpdate
from .controller.templates.dynamips_templates import (
C1700DynamipsTemplate,
C1700DynamipsTemplateUpdate,
C2600DynamipsTemplate,
C2600DynamipsTemplateUpdate,
C2691DynamipsTemplate,
C2691DynamipsTemplateUpdate,
C3600DynamipsTemplate,
C3600DynamipsTemplateUpdate,
C3725DynamipsTemplate,
C3725DynamipsTemplateUpdate,
C3745DynamipsTemplate,
C3745DynamipsTemplateUpdate,
C7200DynamipsTemplate,
C7200DynamipsTemplateUpdate,
DynamipsTemplate,
)
from .controller.templates.ethernet_hub_templates import EthernetHubTemplate, EthernetHubTemplateUpdate
from .controller.templates.ethernet_switch_templates import EthernetSwitchTemplate, EthernetSwitchTemplateUpdate
from .controller.templates.iou_templates import IOUTemplate, IOUTemplateUpdate
from .controller.templates.qemu_templates import QemuTemplate, QemuTemplateUpdate
from .controller.templates.virtualbox_templates import VirtualBoxTemplate, VirtualBoxTemplateUpdate
from .controller.templates.vmware_templates import VMwareTemplate, VMwareTemplateUpdate
# Controller template schemas
from .controller.templates.vpcs_templates import VPCSTemplate, VPCSTemplateUpdate
from .controller.tokens import ApiKeyCreate, RefreshTokenRequest, Token
# Schemas for both controller and compute
from .qemu_disk_image import QemuDiskImageCreate, QemuDiskImageFormat, QemuDiskImageUpdate
__all__ = [
"ACE",
"GNS3VM",
"IOU",
"NAT",
"TAPNIO",
"UDPNIO",
"VPCS",
"ACECreate",
"ACEUpdate",
"ATMSwitch",
"ATMSwitchCreate",
"ATMSwitchUpdate",
"ApiKeyCreate",
"Appliance",
"ApplianceVersion",
"ApplianceVersionV8",
"AutoIdlePC",
"AnchorNIO",
"BatchNIOCreate",
"BatchNIOEntry",
"BridgeNIO",
"C1700DynamipsTemplate",
"C1700DynamipsTemplateUpdate",
"C2600DynamipsTemplate",
"C2600DynamipsTemplateUpdate",
"C2691DynamipsTemplate",
"C2691DynamipsTemplateUpdate",
"C3600DynamipsTemplate",
"C3600DynamipsTemplateUpdate",
"C3725DynamipsTemplate",
"C3725DynamipsTemplateUpdate",
"C3745DynamipsTemplate",
"C3745DynamipsTemplateUpdate",
"C7200DynamipsTemplate",
"C7200DynamipsTemplateUpdate",
"Capabilities",
"ChatRequest",
"ChatResponse",
"ChatSession",
"Cloud",
"CloudCreate",
"CloudTemplate",
"CloudTemplateUpdate",
"CloudUpdate",
"Compute",
"ComputeCreate",
"ComputeDockerImage",
"ComputeUpdate",
"ComputeVMwareVM",
"ComputeVirtualBoxVM",
"ConversationHistory",
"Credentials",
"Docker",
"DockerCreate",
"DockerTemplate",
"DockerTemplateUpdate",
"DockerUpdate",
"Drawing",
"Dynamips",
"DynamipsCreate",
"DynamipsTemplate",
"DynamipsUpdate",
"ErrorMessage",
"EthernetHub",
"EthernetHubCreate",
"EthernetHubTemplate",
"EthernetHubTemplateUpdate",
"EthernetHubUpdate",
"EthernetNIO",
"EthernetPortInfo",
"EthernetSwitch",
"EthernetSwitchCreate",
"EthernetSwitchTemplate",
"EthernetSwitchTemplateUpdate",
"EthernetSwitchUpdate",
"FrameRelaySwitch",
"FrameRelaySwitchCreate",
"FrameRelaySwitchUpdate",
"IOUCreate",
"IOULicense",
"IOUStart",
"IOUTemplate",
"IOUTemplateUpdate",
"IOUUpdate",
"Image",
"ImageSyncJob",
"ImageSyncRequest",
"ImageType",
"LLMModelConfigCreate",
"LLMModelConfigData",
"LLMModelConfigInheritedResponse",
"LLMModelConfigListResponse",
"LLMModelConfigResponse",
"LLMModelConfigUpdate",
"LLMModelConfigWithSource",
"Link",
"LinkCapture",
"LinkCreate",
"LinkUpdate",
"LoggedInUserUpdate",
"MarkerCreate",
"MarkerDefinitionCreate",
"MarkerRebuild",
"MarkerToggle",
"MarkerUpdate",
"NATCreate",
"NATUpdate",
"NetmikoDeviceType",
"NetmikoDeviceTypeList",
"Node",
"NodeCapture",
"NodeCreate",
"NodeDuplicate",
"NodeFile",
"NodeUpdate",
"OpenAIMessage",
"OpenAIToolCall",
"Privilege",
"Project",
"ProjectCompression",
"ProjectCreate",
"ProjectDuplicate",
"ProjectFile",
"ProjectUpdate",
"Qemu",
"QemuCreate",
"QemuDiskImageCreate",
"QemuDiskImageFormat",
"QemuDiskImageUpdate",
"QemuTemplate",
"QemuTemplateUpdate",
"QemuUpdate",
"RefreshTokenRequest",
"RenameSession",
"Resource",
"ResourceCreate",
"ResourcePool",
"ResourcePoolCreate",
"ResourcePoolUpdate",
"Role",
"RoleCreate",
"RoleUpdate",
"ServerConfig",
"SettingsResponse",
"SettingsUpdate",
"SettingsUpdateResponse",
"Snapshot",
"SnapshotCreate",
"Template",
"TemplateCreate",
"TemplateUpdate",
"TemplateUsage",
"Token",
"UDPPortInfo",
"User",
"UserCreate",
"UserGroup",
"UserGroupCreate",
"UserGroupUpdate",
"UserUpdate",
"VMware",
"VMwareCreate",
"VMwareTemplate",
"VMwareTemplateUpdate",
"VMwareUpdate",
"VPCSCreate",
"VPCSTemplate",
"VPCSTemplateUpdate",
"VPCSUpdate",
"Version",
"VirtualBox",
"VirtualBoxCreate",
"VirtualBoxTemplate",
"VirtualBoxTemplateUpdate",
"VirtualBoxUpdate",
]