Skip to content

Commit

Permalink
feat: add BridgePort property to network machine configuration
Browse files Browse the repository at this point in the history
Allow putting a device into a bridge from device configuration.

Signed-off-by: Joakim Nohlgård <joakim@nohlgard.se>
Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
  • Loading branch information
jnohlgard authored and smira committed Oct 30, 2024
1 parent b379506 commit 0b8b356
Show file tree
Hide file tree
Showing 15 changed files with 218 additions and 20 deletions.
2 changes: 1 addition & 1 deletion api/resource/definitions/network/network.proto
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ message BridgeMasterSpec {
BridgeVLANSpec vlan = 2;
}

// BridgeSlave contains a bond's master name and slave index.
// BridgeSlave contains the name of the master bridge of a bridged interface
message BridgeSlave {
string master_name = 1;
}
Expand Down
18 changes: 14 additions & 4 deletions internal/app/machined/pkg/controllers/network/link_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,6 @@ func (ctrl *LinkConfigController) processDevicesConfiguration(logger *zap.Logger
continue
}

if device.Bond() == nil && device.Bridge() == nil {
continue
}

if device.Bond() != nil {
for idx, linkName := range device.Bond().Interfaces() {
if bondData, exists := bondedLinks[linkName]; exists && bondData.F1 != device.Interface() {
Expand Down Expand Up @@ -315,6 +311,20 @@ func (ctrl *LinkConfigController) processDevicesConfiguration(logger *zap.Logger
bridgedLinks[linkName] = device.Interface()
}
}

if device.BridgePort() != nil {
if bridgeName, exists := bridgedLinks[device.Interface()]; exists && bridgeName != device.BridgePort().Master() {
logger.Sugar().Warnf("link %q is included in both bridges %q and %q", device.Interface(),
bridgeName, device.BridgePort().Master())
}

if bondData, exists := bondedLinks[device.Interface()]; exists {
logger.Sugar().Warnf("link %q is included into both bond %q and bridge %q", device.Interface(),
bondData.F1, device.BridgePort().Master())
}

bridgedLinks[device.Interface()] = device.BridgePort().Master()
}
}

linkMap := map[string]*network.LinkSpecSpec{}
Expand Down
23 changes: 23 additions & 0 deletions internal/app/machined/pkg/controllers/network/link_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ func (suite *LinkConfigSuite) TestMachineConfiguration() {
DeviceInterface: "eth5",
DeviceAddresses: []string{"192.168.0.43/24"},
},
{
DeviceInterface: "eth8",
DeviceBridgePort: &v1alpha1.BridgePort{
BridgePortMaster: "br1",
},
},
{
DeviceInterface: "br0",
DeviceBridge: &v1alpha1.Bridge{
Expand All @@ -223,6 +229,10 @@ func (suite *LinkConfigSuite) TestMachineConfiguration() {
},
},
},
{
DeviceInterface: "br1",
DeviceBridge: &v1alpha1.Bridge{},
},
{
DeviceInterface: "br0",
DeviceBridge: &v1alpha1.Bridge{
Expand Down Expand Up @@ -287,9 +297,11 @@ func (suite *LinkConfigSuite) TestMachineConfiguration() {
"configuration/eth3",
"configuration/eth6",
"configuration/eth7",
"configuration/eth8",
"configuration/bond0",
"configuration/bond1",
"configuration/br0",
"configuration/br1",
"configuration/dummy0",
"configuration/wireguard0",
}, func(r *network.LinkSpec, asrt *assert.Assertions) {
Expand Down Expand Up @@ -346,13 +358,24 @@ func (suite *LinkConfigSuite) TestMachineConfiguration() {
asrt.True(r.TypedSpec().Up)
asrt.False(r.TypedSpec().Logical)
asrt.Equal("br0", r.TypedSpec().BridgeSlave.MasterName)
case "eth8":
asrt.True(r.TypedSpec().Up)
asrt.False(r.TypedSpec().Logical)
asrt.Equal("br1", r.TypedSpec().BridgeSlave.MasterName)
case "br0":
asrt.True(r.TypedSpec().Up)
asrt.True(r.TypedSpec().Logical)
asrt.Equal(nethelpers.LinkEther, r.TypedSpec().Type)
asrt.Equal(network.LinkKindBridge, r.TypedSpec().Kind)
asrt.True(r.TypedSpec().BridgeMaster.STP.Enabled)
asrt.True(r.TypedSpec().BridgeMaster.VLAN.FilteringEnabled)
case "br1":
asrt.True(r.TypedSpec().Up)
asrt.True(r.TypedSpec().Logical)
asrt.Equal(nethelpers.LinkEther, r.TypedSpec().Type)
asrt.Equal(network.LinkKindBridge, r.TypedSpec().Kind)
asrt.True(r.TypedSpec().BridgeMaster.STP.Enabled)
asrt.False(r.TypedSpec().BridgeMaster.VLAN.FilteringEnabled)
case "wireguard0":
asrt.True(r.TypedSpec().Up)
asrt.True(r.TypedSpec().Logical)
Expand Down
17 changes: 10 additions & 7 deletions internal/app/machined/pkg/controllers/network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,16 @@ func SetBridgeMaster(link *network.LinkSpecSpec, bridge talosconfig.Bridge) erro
link.Logical = true
link.Kind = network.LinkKindBridge
link.Type = nethelpers.LinkEther
link.BridgeMaster = network.BridgeMasterSpec{
STP: network.STPSpec{
Enabled: bridge.STP().Enabled(),
},
VLAN: network.BridgeVLANSpec{
FilteringEnabled: bridge.VLAN().FilteringEnabled(),
},

if bridge != nil {
link.BridgeMaster = network.BridgeMasterSpec{
STP: network.STPSpec{
Enabled: bridge.STP().Enabled(),
},
VLAN: network.BridgeVLANSpec{
FilteringEnabled: bridge.VLAN().FilteringEnabled(),
},
}
}

return nil
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions pkg/machinery/config/config/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ type Device interface {
Routes() []Route
Bond() Bond
Bridge() Bridge
BridgePort() BridgePort
Vlans() []Vlan
MTU() int
DHCP() bool
Expand Down Expand Up @@ -261,6 +262,11 @@ type Bridge interface {
VLAN() BridgeVLAN
}

// BridgePort contains the options for a bridge port.
type BridgePort interface {
Master() string
}

// Vlan represents vlan settings for a device.
type Vlan interface {
Addresses() []string
Expand Down
20 changes: 20 additions & 0 deletions pkg/machinery/config/schemas/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,19 @@
"additionalProperties": false,
"type": "object"
},
"v1alpha1.BridgePort": {
"properties": {
"master": {
"type": "string",
"title": "master",
"description": "The name of the bridge master interface\n",
"markdownDescription": "The name of the bridge master interface",
"x-intellij-html-description": "\u003cp\u003eThe name of the bridge master interface\u003c/p\u003e\n"
}
},
"additionalProperties": false,
"type": "object"
},
"v1alpha1.BridgeVLAN": {
"properties": {
"vlanFiltering": {
Expand Down Expand Up @@ -1482,6 +1495,13 @@
"markdownDescription": "Bridge specific options.",
"x-intellij-html-description": "\u003cp\u003eBridge specific options.\u003c/p\u003e\n"
},
"bridgePort": {
"$ref": "#/$defs/v1alpha1.BridgePort",
"title": "bridgePort",
"description": "Configure this device as a bridge port.\nThis can be used to dynamically assign network interfaces to a bridge.\n",
"markdownDescription": "Configure this device as a bridge port.\nThis can be used to dynamically assign network interfaces to a bridge.",
"x-intellij-html-description": "\u003cp\u003eConfigure this device as a bridge port.\nThis can be used to dynamically assign network interfaces to a bridge.\u003c/p\u003e\n"
},
"vlans": {
"items": {
"$ref": "#/$defs/v1alpha1.Vlan"
Expand Down
6 changes: 6 additions & 0 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_examples.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,12 @@ func networkConfigBridgeExample() *Bridge {
}
}

func networkConfigDynamicBridgePortsExample() *BridgePort {
return &BridgePort{
BridgePortMaster: "br0",
}
}

func networkConfigDHCPOptionsExample() *DHCPOptions {
return &DHCPOptions{
DHCPRouteMetric: 1024,
Expand Down
18 changes: 18 additions & 0 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,15 @@ func (d *Device) Bridge() config.Bridge {
return d.DeviceBridge
}

// BridgePort implements the MachineNetwork interface.
func (d *Device) BridgePort() config.BridgePort {
if d.DeviceBridgePort == nil {
return nil
}

return d.DeviceBridgePort
}

// Vlans implements the MachineNetwork interface.
func (d *Device) Vlans() []config.Vlan {
return xslices.Map(d.DeviceVlans, func(v *Vlan) config.Vlan { return v })
Expand Down Expand Up @@ -1076,6 +1085,15 @@ func (b *Bridge) VLAN() config.BridgeVLAN {
return b.BridgeVLAN
}

// Master implements the config.BridgePort interface.
func (b *BridgePort) Master() string {
if b == nil {
return ""
}

return b.BridgePortMaster
}

// Addresses implements the MachineNetwork interface.
func (v *Vlan) Addresses() []string {
switch {
Expand Down
12 changes: 12 additions & 0 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1747,6 +1747,12 @@ type Device struct {
// examples:
// - value: networkConfigBridgeExample()
DeviceBridge *Bridge `yaml:"bridge,omitempty"`
// description: |
// Configure this device as a bridge port.
// This can be used to dynamically assign network interfaces to a bridge.
// examples:
// - value: networkConfigDynamicBridgePortsExample()
DeviceBridgePort *BridgePort `yaml:"bridgePort,omitempty"`
// description: VLAN specific options.
DeviceVlans VlanList `yaml:"vlans,omitempty"`
// description: |
Expand Down Expand Up @@ -2006,6 +2012,12 @@ type Bridge struct {
BridgeVLAN *BridgeVLAN `yaml:"vlan,omitempty"`
}

// BridgePort contains settings for assigning a link to a bridge interface.
type BridgePort struct {
// description: The name of the bridge master interface
BridgePortMaster string `yaml:"master,omitempty"`
}

// VlanList is a list of *Vlan structures with overridden merge process.
//
//docgen:alias
Expand Down
46 changes: 41 additions & 5 deletions pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/machinery/resources/network/link_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ type BondSlave struct {
SlaveIndex int `yaml:"slaveIndex,omitempty" protobuf:"2"`
}

// BridgeSlave contains a bond's master name and slave index.
// BridgeSlave contains the name of the master bridge of a bridged interface
//
//gotagsrewrite:gen
type BridgeSlave struct {
Expand Down
2 changes: 1 addition & 1 deletion website/content/v1.9/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -3368,7 +3368,7 @@ BridgeMasterSpec describes bridge settings if Kind == "bridge".
<a name="talos.resource.definitions.network.BridgeSlave"></a>

### BridgeSlave
BridgeSlave contains a bond's master name and slave index.
BridgeSlave contains the name of the master bridge of a bridged interface


| Field | Type | Label | Description |
Expand Down
Loading

0 comments on commit 0b8b356

Please sign in to comment.