Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCPBUGS-48089: validate hostPrefix to be the same when multiple clusternetwork CIDRs are present #9398

Merged
merged 2 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions data/data/install.openshift.io_installconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2378,6 +2378,8 @@ spec:
HostPrefix is the prefix size to allocate to each node from the CIDR.
For example, 24 would allocate 2^8=256 adresses to each node. If this
field is not used by the plugin, it can be left unset.
When multiple CIDRs of the same family (i.e. IPv4/IPv6) are present,
their HostPrefix value must be the same.
format: int32
type: integer
hostSubnetLength:
Expand Down Expand Up @@ -2413,6 +2415,8 @@ spec:
HostPrefix is the prefix size to allocate to each node from the CIDR.
For example, 24 would allocate 2^8=256 adresses to each node. If this
field is not used by the plugin, it can be left unset.
When multiple CIDRs of the same family (i.e. IPv4/IPv6) are present,
their HostPrefix value must be the same.
format: int32
type: integer
hostSubnetLength:
Expand Down
2 changes: 1 addition & 1 deletion docs/user/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ feature set.
The default is 10.128.0.0/14 with a host prefix of /23.
* `cidr` (required [IP network](#ip-networks)): The IP block address pool.
* `hostPrefix` (required integer): The prefix size to allocate to each node from the CIDR.
For example, 24 would allocate 2^8=256 addresses to each node. If this field is not used by the plugin, it can be left unset.
For example, 24 would allocate 2^8=256 addresses to each node. If this field is not used by the plugin, it can be left unset. When multiple CIDRs of the same family (i.e. IPv4/IPv6) are present, their `hostPrefix` value must be the same.
* `machineNetwork` (optional array of objects): The IP address pools for machines.
* `cidr` (required [IP network](#ip-networks)): The IP block address pool.
The default is 10.0.0.0/16 for all platforms other than libvirt.
Expand Down
2 changes: 2 additions & 0 deletions pkg/types/installconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ type ClusterNetworkEntry struct {
// HostPrefix is the prefix size to allocate to each node from the CIDR.
// For example, 24 would allocate 2^8=256 adresses to each node. If this
// field is not used by the plugin, it can be left unset.
// When multiple CIDRs of the same family (i.e. IPv4/IPv6) are present,
// their HostPrefix value must be the same.
// +optional
HostPrefix int32 `json:"hostPrefix,omitempty"`

Expand Down
17 changes: 13 additions & 4 deletions pkg/types/validation/installconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,13 +502,22 @@ func validateClusterNetwork(n *types.Networking, cn *types.ClusterNetworkEntry,
allErrs = append(allErrs, field.Invalid(fldPath.Child("cidr"), cn.CIDR.String(), fmt.Sprintf("cluster network must not overlap with cluster network %d", i)))
}
}
if cn.HostPrefix < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPrefix"), cn.HostPrefix, "hostPrefix must be positive"))
}

// ignore hostPrefix if the plugin does not use it and has it unset
if pluginsUsingHostPrefix.Has(n.NetworkType) || (cn.HostPrefix != 0) {
if ones, bits := cn.CIDR.Mask.Size(); cn.HostPrefix < int32(ones) {
if cn.HostPrefix < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPrefix"), cn.HostPrefix, "hostPrefix must be positive"))
} else if ones, bits := cn.CIDR.Mask.Size(); cn.HostPrefix < int32(ones) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPrefix"), cn.HostPrefix, "cluster network host subnetwork prefix must not be larger size than CIDR "+cn.CIDR.String()))
} else if bits == 32 {
// setting different value for clusternetwork CIDR host prefix is not allowed
// we only need to check IPv4 as IPv6 prefix must be 64
for _, acn := range n.ClusterNetwork[0:idx] {
if acn.CIDR.IP.To4() != nil && cn.HostPrefix != acn.HostPrefix {
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPrefix"), cn.HostPrefix, "cluster network host subnetwork prefix must be the same value for IPv4 networks"))
break
}
}
} else if bits == 128 && cn.HostPrefix != 64 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPrefix"), cn.HostPrefix, "cluster network host subnetwork prefix must be 64 for IPv6 networks"))
}
Expand Down
31 changes: 29 additions & 2 deletions pkg/types/validation/installconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -516,8 +516,8 @@ func TestValidateInstallConfig(t *testing.T) {
installConfig: func() *types.InstallConfig {
c := validInstallConfig()
c.Networking.ClusterNetwork = []types.ClusterNetworkEntry{
{CIDR: *ipnet.MustParseCIDR("12.0.0.0/16"), HostPrefix: 23},
{CIDR: *ipnet.MustParseCIDR("12.0.3.0/24"), HostPrefix: 25},
{CIDR: *ipnet.MustParseCIDR("12.0.0.0/16"), HostPrefix: 28},
{CIDR: *ipnet.MustParseCIDR("12.0.3.0/24"), HostPrefix: 28},
}
return c
}(),
Expand Down Expand Up @@ -554,6 +554,33 @@ func TestValidateInstallConfig(t *testing.T) {
}(),
expectedError: ``,
},
{
name: "cluster network host prefix negative",
installConfig: func() *types.InstallConfig {
c := validInstallConfig()
c.Networking.ClusterNetwork[0].HostPrefix = -23
return c
}(),
expectedError: `^networking\.clusterNetwork\[0]\.hostPrefix: Invalid value: -23: hostPrefix must be positive$`,
},
{
name: "multiple cluster network host prefix different",
installConfig: func() *types.InstallConfig {
c := validInstallConfig()
c.Networking.ClusterNetwork = append(c.Networking.ClusterNetwork,
types.ClusterNetworkEntry{
CIDR: *ipnet.MustParseCIDR("192.168.2.0/24"),
HostPrefix: 30,
},
types.ClusterNetworkEntry{
CIDR: *ipnet.MustParseCIDR("ffd2::/48"),
HostPrefix: 64,
},
patrickdillon marked this conversation as resolved.
Show resolved Hide resolved
)
return c
}(),
expectedError: `^networking\.clusterNetwork\[1]\.hostPrefix: Invalid value: 30: cluster network host subnetwork prefix must be the same value for IPv4 networks$`,
},
{
name: "networking clusterNetworkMTU - valid high limit ovn",
installConfig: func() *types.InstallConfig {
Expand Down