diff --git a/internal/app/machined/pkg/controllers/network/operator_config.go b/internal/app/machined/pkg/controllers/network/operator_config.go
index c46f9ef7b..f6acd5f56 100644
--- a/internal/app/machined/pkg/controllers/network/operator_config.go
+++ b/internal/app/machined/pkg/controllers/network/operator_config.go
@@ -152,13 +152,36 @@ func (ctrl *OperatorConfigController) Run(ctx context.Context, r controller.Runt
}
for _, vlan := range device.Vlans() {
- if vlan.DHCP() {
+ if vlan.DHCP() && vlan.DHCPOptions().IPv4() {
+ routeMetric := vlan.DHCPOptions().RouteMetric()
+ if routeMetric == 0 {
+ routeMetric = DefaultRouteMetric
+ }
+
specs = append(specs, network.OperatorSpecSpec{
Operator: network.OperatorDHCP4,
LinkName: fmt.Sprintf("%s.%d", device.Interface(), vlan.ID()),
RequireUp: true,
DHCP4: network.DHCP4OperatorSpec{
- RouteMetric: DefaultRouteMetric,
+ RouteMetric: routeMetric,
+ },
+ ConfigLayer: network.ConfigMachineConfiguration,
+ })
+ }
+
+ if vlan.DHCP() && vlan.DHCPOptions().IPv6() {
+ routeMetric := vlan.DHCPOptions().RouteMetric()
+ if routeMetric == 0 {
+ routeMetric = DefaultRouteMetric
+ }
+
+ specs = append(specs, network.OperatorSpecSpec{
+ Operator: network.OperatorDHCP6,
+ LinkName: fmt.Sprintf("%s.%d", device.Interface(), vlan.ID()),
+ RequireUp: true,
+ DHCP6: network.DHCP6OperatorSpec{
+ RouteMetric: routeMetric,
+ DUID: vlan.DHCPOptions().DUIDv6(),
},
ConfigLayer: network.ConfigMachineConfiguration,
})
diff --git a/internal/app/machined/pkg/controllers/network/operator_config_test.go b/internal/app/machined/pkg/controllers/network/operator_config_test.go
index 111005b7b..9cae10595 100644
--- a/internal/app/machined/pkg/controllers/network/operator_config_test.go
+++ b/internal/app/machined/pkg/controllers/network/operator_config_test.go
@@ -305,6 +305,12 @@ func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP4() {
{
VlanID: 26,
},
+ {
+ VlanID: 27,
+ VlanDHCPOptions: &v1alpha1.DHCPOptions{
+ DHCPRouteMetric: 256,
+ },
+ },
},
},
{
@@ -348,6 +354,12 @@ func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP4() {
case "configuration/dhcp4/eth4.25":
suite.Assert().Equal("eth4.25", r.TypedSpec().LinkName)
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
+ case "configuration/dhcp4/eth4.26":
+ suite.Assert().Equal("eth4.26", r.TypedSpec().LinkName)
+ suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
+ case "configuration/dhcp4/eth4.27":
+ suite.Assert().Equal("eth4.27", r.TypedSpec().LinkName)
+ suite.Assert().EqualValues(256, r.TypedSpec().DHCP4.RouteMetric)
}
return nil
diff --git a/pkg/machinery/config/provider.go b/pkg/machinery/config/provider.go
index a948e6178..e4cbf7d78 100644
--- a/pkg/machinery/config/provider.go
+++ b/pkg/machinery/config/provider.go
@@ -268,6 +268,7 @@ type Vlan interface {
ID() uint16
MTU() uint32
VIPConfig() VIPConfig
+ DHCPOptions() DHCPOptions
}
// Route represents a network route.
diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go
index 7b06c6175..70b83abe4 100644
--- a/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go
+++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go
@@ -977,6 +977,18 @@ func (v *Vlan) DHCP() bool {
return pointer.SafeDeref(v.VlanDHCP)
}
+// DHCPOptions implements the MachineNetwork interface.
+func (v *Vlan) DHCPOptions() config.DHCPOptions {
+ // Default route metric on systemd is 1024. This sets the same.
+ if v.VlanDHCPOptions == nil {
+ return &DHCPOptions{
+ DHCPRouteMetric: uint32(0),
+ }
+ }
+
+ return v.VlanDHCPOptions
+}
+
// ID implements the MachineNetwork interface.
func (v *Vlan) ID() uint16 {
return v.VlanID
diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go
index 4d5e85092..bf88c3779 100644
--- a/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go
+++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_types.go
@@ -2250,6 +2250,10 @@ type Vlan struct {
VlanMTU uint32 `yaml:"mtu,omitempty"`
// description: The VLAN's virtual IP address configuration.
VlanVIP *DeviceVIPConfig `yaml:"vip,omitempty"`
+ // description: |
+ // DHCP specific options.
+ // `dhcp` *must* be set to true for these to take effect.
+ VlanDHCPOptions *DHCPOptions `yaml:"dhcpOptions,omitempty"`
}
// Route represents a network route.
diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go
index 292e8cb82..d2a62eb80 100644
--- a/pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go
+++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_types_doc.go
@@ -1740,6 +1740,10 @@ func init() {
TypeName: "Device",
FieldName: "dhcpOptions",
},
+ {
+ TypeName: "Vlan",
+ FieldName: "dhcpOptions",
+ },
}
DHCPOptionsDoc.Fields = make([]encoder.Doc, 4)
DHCPOptionsDoc.Fields[0].Name = "routeMetric"
@@ -2089,7 +2093,7 @@ func init() {
FieldName: "vlans",
},
}
- VlanDoc.Fields = make([]encoder.Doc, 7)
+ VlanDoc.Fields = make([]encoder.Doc, 8)
VlanDoc.Fields[0].Name = "addresses"
VlanDoc.Fields[0].Type = "[]string"
VlanDoc.Fields[0].Note = ""
@@ -2120,6 +2124,11 @@ func init() {
VlanDoc.Fields[6].Note = ""
VlanDoc.Fields[6].Description = "The VLAN's virtual IP address configuration."
VlanDoc.Fields[6].Comments[encoder.LineComment] = "The VLAN's virtual IP address configuration."
+ VlanDoc.Fields[7].Name = "dhcpOptions"
+ VlanDoc.Fields[7].Type = "DHCPOptions"
+ VlanDoc.Fields[7].Note = ""
+ VlanDoc.Fields[7].Description = "DHCP specific options.\n`dhcp` *must* be set to true for these to take effect."
+ VlanDoc.Fields[7].Comments[encoder.LineComment] = "DHCP specific options."
RouteDoc.Type = "Route"
RouteDoc.Comments[encoder.LineComment] = "Route represents a network route."
diff --git a/pkg/machinery/config/types/v1alpha1/zz_generated.deepcopy.go b/pkg/machinery/config/types/v1alpha1/zz_generated.deepcopy.go
index 5c525819d..e1aca5a82 100644
--- a/pkg/machinery/config/types/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/machinery/config/types/v1alpha1/zz_generated.deepcopy.go
@@ -2084,6 +2084,11 @@ func (in *Vlan) DeepCopyInto(out *Vlan) {
*out = new(DeviceVIPConfig)
(*in).DeepCopyInto(*out)
}
+ if in.VlanDHCPOptions != nil {
+ in, out := &in.VlanDHCPOptions, &out.VlanDHCPOptions
+ *out = new(DHCPOptions)
+ (*in).DeepCopyInto(*out)
+ }
return
}
diff --git a/website/content/v1.2/reference/configuration.md b/website/content/v1.2/reference/configuration.md
index a2e7fdd48..aa7e3ba57 100644
--- a/website/content/v1.2/reference/configuration.md
+++ b/website/content/v1.2/reference/configuration.md
@@ -2087,6 +2087,7 @@ DHCPOptions contains options for configuring the DHCP settings for a given inter
Appears in:
- Device.dhcpOptions
+- Vlan.dhcpOptions
@@ -2342,6 +2343,7 @@ Appears in:
|`vlanId` |uint16 |The VLAN's ID. | |
|`mtu` |uint32 |The VLAN's MTU. | |
|`vip` |DeviceVIPConfig |The VLAN's virtual IP address configuration. | |
+|`dhcpOptions` |DHCPOptions |DHCP specific options.
`dhcp` *must* be set to true for these to take effect. | |