diff --git a/pkg/config/validation/validation.go b/pkg/config/validation/validation.go index 547ad509aa68..f61fa980526c 100644 --- a/pkg/config/validation/validation.go +++ b/pkg/config/validation/validation.go @@ -18,6 +18,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "net" "net/http" "net/url" @@ -1064,12 +1065,41 @@ func validateLoadBalancer(settings *networking.LoadBalancerSettings, outlier *ne if consistentHash.MinimumRingSize != 0 && consistentHash.GetHashAlgorithm() != nil { errs = AppendValidation(errs, fmt.Errorf("only one of MinimumRingSize or Maglev/Ringhash can be specified")) } + if ml := consistentHash.GetMaglev(); ml != nil { + if ml.TableSize == 0 { + errs = AppendValidation(errs, fmt.Errorf("tableSize must be set for maglev")) + } + if ml.TableSize >= 5000011 { + errs = AppendValidation(errs, fmt.Errorf("tableSize must be less than 5000011 for maglev")) + } + if !isPrime(ml.TableSize) { + errs = AppendValidation(errs, fmt.Errorf("tableSize must be a prime number for maglev")) + } + } } errs = AppendValidation(errs, agent.ValidateLocalityLbSetting(settings.LocalityLbSetting, outlier)) return } +// Copied from https://github.com/envoyproxy/envoy/blob/5451efd9b8f8a444431197050e45ba974ed4e9d8/source/common/common/utility.cc#L601-L615 +// to ensure we 100% match Envoy's implementation +func isPrime(x uint64) bool { + if x != 0 && x < 4 { + return true // eliminates special-casing 2. + } else if (x & 1) == 0 { + return false // eliminates even numbers >2. + } + + limit := uint64(math.Sqrt(float64(x))) + for factor := uint64(3); factor <= limit; factor += 2 { + if (x % factor) == 0 { + return false + } + } + return true +} + func validateSubset(subset *networking.Subset) error { return appendErrors(validateSubsetName(subset.Name), labels.Instance(subset.Labels).Validate(), diff --git a/pkg/config/validation/validation_test.go b/pkg/config/validation/validation_test.go index 8474f373da06..2da62a28a840 100644 --- a/pkg/config/validation/validation_test.go +++ b/pkg/config/validation/validation_test.go @@ -3195,6 +3195,19 @@ func TestValidateLoadBalancer(t *testing.T) { }, valid: false, }, + + { + name: "invalid load balancer with consistentHash load balancing, maglev not prime", in: &networking.LoadBalancerSettings{ + LbPolicy: &networking.LoadBalancerSettings_ConsistentHash{ + ConsistentHash: &networking.LoadBalancerSettings_ConsistentHashLB{ + HashAlgorithm: &networking.LoadBalancerSettings_ConsistentHashLB_Maglev{ + Maglev: &networking.LoadBalancerSettings_ConsistentHashLB_MagLev{TableSize: 1000}, + }, + }, + }, + }, + valid: false, + }, } for _, c := range cases {