Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions internal/server/device/nic_physical.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ func (d *nicPhysical) validateConfig(instConf instance.ConfigReader) error {
// Get actual parent device from network's parent setting.
d.config["parent"] = netConfig["parent"]

// If parent is a bridge, ensure it's managed.
isParentBridge := d.config["parent"] != "" && util.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", d.config["parent"]))
if isParentBridge && d.network == nil {
return fmt.Errorf("Parent device is a bridge, use nictype=bridged instead")
}

// Copy certain keys verbatim from the network's settings.
for _, field := range optionalFields {
_, found := netConfig[field]
Expand Down Expand Up @@ -174,6 +180,25 @@ func (d *nicPhysical) Start() (*deviceConfig.RunConfig, error) {
return nil, err
}

// Handle the case where the parent is a bridge.
isParentBridge := util.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", d.config["parent"]))
if isParentBridge {
// Convert the device to a nictype=bridged internally.
bridgedConfig := d.config.Clone()
bridgedConfig["type"] = "nic"
bridgedConfig["nictype"] = "bridged"
bridgedConfig["network"] = ""

// Instantiate the new device.
bridged, err := load(d.inst, d.state, d.inst.Project().Name, d.inst.Name(), bridgedConfig, d.volatileGet, d.volatileSet)
if err != nil {
return nil, fmt.Errorf("Failed to initialize bridged device: %w", err)
}

// Forward the start call.
return bridged.Start()
}

// Lock to avoid issues with containers starting in parallel.
networkCreateSharedDeviceLock.Lock()
defer networkCreateSharedDeviceLock.Unlock()
Expand Down Expand Up @@ -374,6 +399,25 @@ func (d *nicPhysical) startVMUSB(name string) (*deviceConfig.RunConfig, error) {

// Stop is run when the device is removed from the instance.
func (d *nicPhysical) Stop() (*deviceConfig.RunConfig, error) {
// Handle the case where the parent is a bridge.
isParentBridge := util.PathExists(fmt.Sprintf("/sys/class/net/%s/bridge", d.config["parent"]))
if isParentBridge {
// Convert the device to a nictype=bridged internally.
bridgedConfig := d.config.Clone()
bridgedConfig["type"] = "nic"
bridgedConfig["nictype"] = "bridged"
bridgedConfig["network"] = ""

// Instantiate the new device.
bridged, err := load(d.inst, d.state, d.inst.Project().Name, d.inst.Name(), bridgedConfig, d.volatileGet, d.volatileSet)
if err != nil {
return nil, fmt.Errorf("Failed to initialize bridged device: %w", err)
}

// Forward the stop call.
return bridged.Stop()
}

v := d.volatileGet()

runConf := deviceConfig.RunConfig{
Expand Down