diff --git a/api/meta/types.go b/api/meta/types.go index 9130c3930..2ef34199c 100644 --- a/api/meta/types.go +++ b/api/meta/types.go @@ -74,6 +74,8 @@ type UserCreds struct { SSHKeys []string `json:"sshKeys,omitempty"` } +var BCMReservedVLANRanges = []VLANRange{{From: 3967, To: 4094}} + type FabricConfig struct { DeploymentID string `json:"deploymentID,omitempty"` ControlVIP string `json:"controlVIP,omitempty"` @@ -260,6 +262,9 @@ func (cfg *FabricConfig) Init() (*FabricConfig, error) { if len(r) == 0 { return nil, errors.Errorf("config: vpcIRBVLANRange is required") } + if err := CheckVLANRangesOverlap(append(slices.Clone(r), BCMReservedVLANRanges...)); err != nil { + return nil, errors.Wrapf(err, "config: vpcIRBVLANRange overlaps with Broadcom reserved VLAN range") + } cfg.VPCIRBVLANRanges = r // TODO check total ranges size and expose as limit for API validation } @@ -270,6 +275,9 @@ func (cfg *FabricConfig) Init() (*FabricConfig, error) { if len(r) == 0 { return nil, errors.Errorf("config: vpcPeeringVLANRange is required") } + if err := CheckVLANRangesOverlap(append(slices.Clone(r), BCMReservedVLANRanges...)); err != nil { + return nil, errors.Wrapf(err, "config: vpcPeeringVLANRange overlaps with Broadcom reserved VLAN range") + } cfg.VPCPeeringVLANRanges = r // TODO check total ranges size and expose as limit for API validation } @@ -280,6 +288,9 @@ func (cfg *FabricConfig) Init() (*FabricConfig, error) { if len(r) == 0 { return nil, errors.Errorf("config: th5WorkaroundVLANRange is required") } + if err := CheckVLANRangesOverlap(append(slices.Clone(r), BCMReservedVLANRanges...)); err != nil { + return nil, errors.Wrapf(err, "config: th5WorkaroundVLANRange overlaps with Broadcom reserved VLAN range") + } cfg.TH5WorkaroundVLANRange = r } diff --git a/api/wiring/v1beta1/vlannamespace_types.go b/api/wiring/v1beta1/vlannamespace_types.go index 62db4e37f..7a82f9cd7 100644 --- a/api/wiring/v1beta1/vlannamespace_types.go +++ b/api/wiring/v1beta1/vlannamespace_types.go @@ -128,6 +128,10 @@ func (ns *VLANNamespace) Validate(_ context.Context, _ kclient.Reader, fabricCfg return nil, errors.Wrapf(err, "invalid ranges") } + if err := meta.CheckVLANRangesOverlap(append(slices.Clone(meta.BCMReservedVLANRanges), ns.Spec.Ranges...)); err != nil { + return nil, errors.Wrapf(err, "ranges overlap with Broadcom reserved VLANs") + } + if fabricCfg != nil { if err := meta.CheckVLANRangesOverlap(append(slices.Clone(fabricCfg.VPCIRBVLANRanges), ns.Spec.Ranges...)); err != nil { return nil, errors.Wrapf(err, "ranges overlap with Fabric reserved VLANs") diff --git a/api/wiring/v1beta1/vlannamespace_types_test.go b/api/wiring/v1beta1/vlannamespace_types_test.go index 7affdd5f5..a3f6c0379 100644 --- a/api/wiring/v1beta1/vlannamespace_types_test.go +++ b/api/wiring/v1beta1/vlannamespace_types_test.go @@ -42,7 +42,7 @@ func vlanNSGen(name string, ranges []meta.VLANRange) *wiringapi.VLANNamespace { func TestValidate(t *testing.T) { cfg := &meta.FabricConfig{ VPCIRBVLANRanges: []meta.VLANRange{{From: 3000, To: 3199}}, - TH5WorkaroundVLANRange: []meta.VLANRange{{From: 3900, To: 3999}}, + TH5WorkaroundVLANRange: []meta.VLANRange{{From: 3900, To: 3966}}, } for _, tt := range []struct { name string @@ -56,7 +56,12 @@ func TestValidate(t *testing.T) { }, { name: "th5-collision", - vlanNS: vlanNSGen("ns-1", []meta.VLANRange{{From: 3500, To: 4500}}), + vlanNS: vlanNSGen("ns-1", []meta.VLANRange{{From: 3500, To: 3950}}), + err: true, + }, + { + name: "bcm-reserved-collision", + vlanNS: vlanNSGen("ns-2", []meta.VLANRange{{From: 4000, To: 4050}}), err: true, }, {