From 5e8ccda71cc676e070cd0f5d7b6990b8ebc24c1f Mon Sep 17 00:00:00 2001 From: "Khaled Henidak(Kal)" Date: Fri, 23 Aug 2019 17:25:59 +0000 Subject: [PATCH 1/4] phase 2: api types + defaulting + validation + disabled fields handling --- pkg/apis/core/fuzzer/fuzzer.go | 5 + pkg/apis/core/types.go | 21 +++ pkg/apis/core/v1/defaults.go | 31 ++++ pkg/apis/core/v1/defaults_test.go | 138 ++++++++++++++++++ pkg/apis/core/validation/validation.go | 26 +++- pkg/apis/core/validation/validation_test.go | 99 +++++++++++++ pkg/registry/core/service/strategy.go | 18 +++ pkg/registry/core/service/strategy_test.go | 74 ++++++++++ staging/publishing/import-restrictions.yaml | 1 + staging/src/k8s.io/api/core/v1/types.go | 21 +++ .../pkg/describe/versioned/describe.go | 5 + .../pkg/describe/versioned/describe_test.go | 48 +++++- 12 files changed, 483 insertions(+), 4 deletions(-) diff --git a/pkg/apis/core/fuzzer/fuzzer.go b/pkg/apis/core/fuzzer/fuzzer.go index 23eb3cf61dd..44517298295 100644 --- a/pkg/apis/core/fuzzer/fuzzer.go +++ b/pkg/apis/core/fuzzer/fuzzer.go @@ -279,6 +279,11 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { types := []core.ServiceType{core.ServiceTypeClusterIP, core.ServiceTypeNodePort, core.ServiceTypeLoadBalancer} *p = types[c.Rand.Intn(len(types))] }, + func(p *core.IPFamily, c fuzz.Continue) { + types := []core.IPFamily{core.IPv4Protocol, core.IPv6Protocol} + selected := types[c.Rand.Intn(len(types))] + *p = selected + }, func(p *core.ServiceExternalTrafficPolicyType, c fuzz.Continue) { types := []core.ServiceExternalTrafficPolicyType{core.ServiceExternalTrafficPolicyTypeCluster, core.ServiceExternalTrafficPolicyTypeLocal} *p = types[c.Rand.Intn(len(types))] diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index b02c5749eba..86025fc09fc 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -3330,6 +3330,17 @@ type LoadBalancerIngress struct { Hostname string } +// IPFamily represents the IP Family (IPv4 or IPv6). This type is used +// to express the family of an IP expressed by a type (i.e. service.Spec.IPFamily) +type IPFamily string + +const ( + // IPv4Protocol indicates that this IP is IPv4 protocol + IPv4Protocol IPFamily = "IPv4" + // IPv6Protocol indicates that this IP is IPv6 protocol + IPv6Protocol IPFamily = "IPv6" +) + // ServiceSpec describes the attributes that a user creates on a service type ServiceSpec struct { // Type determines how the Service is exposed. Defaults to ClusterIP. Valid @@ -3430,6 +3441,16 @@ type ServiceSpec struct { // of peer discovery. // +optional PublishNotReadyAddresses bool + + // ipFamily specifies whether this Service has a preference for a particular IP family (e.g. IPv4 vs. + // IPv6). If a specific IP family is requested, the clusterIP field will be allocated from that family, if it is + // available in the cluster. If no IP family is requested, the cluster's primary IP family will be used. + // Other IP fields (loadBalancerIP, loadBalancerSourceRanges, externalIPs) and controllers which + // allocate external load-balancers should use the same IP family. Endpoints for this Service will be of + // this family. This field is immutable after creation. Assigning a ServiceIPFamily not available in the + // cluster (e.g. IPv6 in IPv4 only cluster) is an error condition and will fail during clusterIP assignment. + // +optional + IPFamily *IPFamily } type ServicePort struct { diff --git a/pkg/apis/core/v1/defaults.go b/pkg/apis/core/v1/defaults.go index 0ec32ebf225..bc56c783076 100644 --- a/pkg/apis/core/v1/defaults.go +++ b/pkg/apis/core/v1/defaults.go @@ -24,6 +24,10 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/parsers" utilpointer "k8s.io/utils/pointer" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" + utilnet "k8s.io/utils/net" ) func addDefaultingFuncs(scheme *runtime.Scheme) error { @@ -128,6 +132,33 @@ func SetDefaults_Service(obj *v1.Service) { obj.Spec.ExternalTrafficPolicy == "" { obj.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeCluster } + + // if dualstack feature gate is on then we need to default + // Spec.IPFamily correctly. This is to cover the case + // when an existing cluster have been converted to dualstack + // i.e. it already contain services with Spec.IPFamily==nil + if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) && + obj.Spec.Type != v1.ServiceTypeExternalName && + obj.Spec.ClusterIP != "" && /*has an ip already set*/ + obj.Spec.ClusterIP != "None" && /* not converting from ExternalName to other */ + obj.Spec.IPFamily == nil /* family was not previously set */ { + + // there is a change that the ClusterIP (set by user) is unparsable. + // in this case, the family will be set mistakenly to ipv4 (because + // the util function does not parse errors *sigh*). The error + // will be caught in validation which asserts the validity of the + // IP and the service object will not be persisted with the wrong IP + // family + + ipv6 := v1.IPv6Protocol + ipv4 := v1.IPv4Protocol + if utilnet.IsIPv6String(obj.Spec.ClusterIP) { + obj.Spec.IPFamily = &ipv6 + } else { + obj.Spec.IPFamily = &ipv4 + } + } + } func SetDefaults_Pod(obj *v1.Pod) { // If limits are specified, but requests are not, default requests to limits diff --git a/pkg/apis/core/v1/defaults_test.go b/pkg/apis/core/v1/defaults_test.go index 4fd112a136a..00e468f2d6b 100644 --- a/pkg/apis/core/v1/defaults_test.go +++ b/pkg/apis/core/v1/defaults_test.go @@ -35,6 +35,10 @@ import ( // enforce that all types are installed _ "k8s.io/kubernetes/pkg/api/testapi" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/kubernetes/pkg/features" ) // TestWorkloadDefaults detects changes to defaults within PodTemplateSpec. @@ -976,6 +980,140 @@ func TestSetDefaultService(t *testing.T) { } } +func TestSetDefaultServiceIPFamily(t *testing.T) { + svc := v1.Service{ + Spec: v1.ServiceSpec{ + SessionAffinity: v1.ServiceAffinityNone, + Type: v1.ServiceTypeClusterIP, + }, + } + testCases := []struct { + name string + inSvcTweak func(s v1.Service) v1.Service + outSvcTweak func(s v1.Service) v1.Service + enableDualStack bool + }{ + { + name: "dualstack off. ipfamily not set", + inSvcTweak: func(s v1.Service) v1.Service { return s }, + outSvcTweak: func(s v1.Service) v1.Service { return s }, + enableDualStack: false, + }, + { + name: "dualstack on. ipfamily not set, service is *not* ClusterIP-able", + inSvcTweak: func(s v1.Service) v1.Service { + s.Spec.Type = v1.ServiceTypeExternalName + return s + }, + outSvcTweak: func(s v1.Service) v1.Service { return s }, + enableDualStack: true, + }, + { + name: "dualstack off. ipfamily set", + inSvcTweak: func(s v1.Service) v1.Service { + ipv4Service := v1.IPv4Protocol + s.Spec.IPFamily = &ipv4Service + return s + }, + outSvcTweak: func(s v1.Service) v1.Service { + ipv4Service := v1.IPv4Protocol + s.Spec.IPFamily = &ipv4Service + return s + }, + enableDualStack: false, + }, + { + name: "dualstack off. ipfamily not set. clusterip set", + inSvcTweak: func(s v1.Service) v1.Service { + s.Spec.ClusterIP = "1.1.1.1" + return s + }, + outSvcTweak: func(s v1.Service) v1.Service { + return s + }, + enableDualStack: false, + }, + { + name: "dualstack on. ipfamily not set (clusterIP is v4)", + inSvcTweak: func(s v1.Service) v1.Service { + s.Spec.ClusterIP = "1.1.1.1" + return s + }, + outSvcTweak: func(s v1.Service) v1.Service { + ipv4Service := v1.IPv4Protocol + s.Spec.IPFamily = &ipv4Service + return s + }, + enableDualStack: true, + }, + { + name: "dualstack on. ipfamily not set (clusterIP is v6)", + inSvcTweak: func(s v1.Service) v1.Service { + s.Spec.ClusterIP = "fdd7:7713:8917:77ed:ffff:ffff:ffff:ffff" + return s + }, + outSvcTweak: func(s v1.Service) v1.Service { + ipv6Service := v1.IPv6Protocol + s.Spec.IPFamily = &ipv6Service + return s + }, + enableDualStack: true, + }, + { + name: "dualstack on. ipfamily set (clusterIP is v4)", + inSvcTweak: func(s v1.Service) v1.Service { + ipv4Service := v1.IPv4Protocol + s.Spec.IPFamily = &ipv4Service + s.Spec.ClusterIP = "1.1.1.1" + return s + }, + outSvcTweak: func(s v1.Service) v1.Service { + ipv4Service := v1.IPv4Protocol + s.Spec.IPFamily = &ipv4Service + return s + }, + enableDualStack: true, + }, + { + name: "dualstack on. ipfamily set (clusterIP is v6)", + inSvcTweak: func(s v1.Service) v1.Service { + ipv6Service := v1.IPv6Protocol + s.Spec.IPFamily = &ipv6Service + s.Spec.ClusterIP = "fdd7:7713:8917:77ed:ffff:ffff:ffff:ffff" + return s + }, + outSvcTweak: func(s v1.Service) v1.Service { + ipv6Service := v1.IPv6Protocol + s.Spec.IPFamily = &ipv6Service + return s + }, + enableDualStack: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.enableDualStack)() + tweakedIn := tc.inSvcTweak(svc) + expectedSvc := tc.outSvcTweak(svc) + defaulted := roundTrip(t, runtime.Object(&tweakedIn)) + + defaultedSvc := defaulted.(*v1.Service) + if expectedSvc.Spec.IPFamily != nil { + if defaultedSvc.Spec.IPFamily == nil { + t.Fatalf("defaulted service ipfamily is nil while expected is not") + } + if *(expectedSvc.Spec.IPFamily) != *(defaultedSvc.Spec.IPFamily) { + t.Fatalf("defaulted service ipfamily %v does not match expected %v", defaultedSvc.Spec.IPFamily, expectedSvc.Spec.IPFamily) + } + } + + if expectedSvc.Spec.IPFamily == nil && defaultedSvc.Spec.IPFamily != nil { + t.Fatalf("defaulted service ipfamily is not nil, while expected service ipfamily is") + } + }) + } +} + func TestSetDefaultServiceSessionAffinityConfig(t *testing.T) { testCases := map[string]v1.Service{ "SessionAffinityConfig is empty": { diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index e135bb277b7..f609b0980b4 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -3893,6 +3893,7 @@ func ValidatePodTemplateUpdate(newPod, oldPod *core.PodTemplate) field.ErrorList var supportedSessionAffinityType = sets.NewString(string(core.ServiceAffinityClientIP), string(core.ServiceAffinityNone)) var supportedServiceType = sets.NewString(string(core.ServiceTypeClusterIP), string(core.ServiceTypeNodePort), string(core.ServiceTypeLoadBalancer), string(core.ServiceTypeExternalName)) +var supportedServiceIPFamily = sets.NewString(string(core.IPv4Protocol), string(core.IPv6Protocol)) // ValidateService tests if required fields/annotations of a Service are valid. func ValidateService(service *core.Service) field.ErrorList { @@ -4064,8 +4065,22 @@ func ValidateService(service *core.Service) field.ErrorList { } } - allErrs = append(allErrs, validateServiceExternalTrafficFieldsValue(service)...) + //if an ipfamily provided then it has to be one of the supported values + // note: + // - we don't validate service.Spec.IPFamily is supported by the cluster + // - we don't validate service.Spec.ClusterIP is within a range supported by the cluster + // both of these validations are done by the ipallocator + // if the gate is on this field is required (and defaulted by REST if not provided by user) + if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) && service.Spec.IPFamily == nil { + allErrs = append(allErrs, field.Required(specPath.Child("ipFamily"), "")) + } + + if service.Spec.IPFamily != nil && !supportedServiceIPFamily.Has(string(*service.Spec.IPFamily)) { + allErrs = append(allErrs, field.NotSupported(specPath.Child("ipFamily"), service.Spec.IPFamily, supportedServiceIPFamily.List())) + } + + allErrs = append(allErrs, validateServiceExternalTrafficFieldsValue(service)...) return allErrs } @@ -4154,12 +4169,19 @@ func ValidateServiceExternalTrafficFieldsCombination(service *core.Service) fiel func ValidateServiceUpdate(service, oldService *core.Service) field.ErrorList { allErrs := ValidateObjectMetaUpdate(&service.ObjectMeta, &oldService.ObjectMeta, field.NewPath("metadata")) - // ClusterIP should be immutable for services using it (every type other than ExternalName) + // ClusterIP and IPFamily should be immutable for services using it (every type other than ExternalName) // which do not have ClusterIP assigned yet (empty string value) if service.Spec.Type != core.ServiceTypeExternalName { if oldService.Spec.Type != core.ServiceTypeExternalName && oldService.Spec.ClusterIP != "" { allErrs = append(allErrs, ValidateImmutableField(service.Spec.ClusterIP, oldService.Spec.ClusterIP, field.NewPath("spec", "clusterIP"))...) } + // notes: + // we drop the IPFamily field when the Dualstack gate is off. + // once the gate is on, we start assigning default ipfamily according to cluster settings. in other words + // though the field is immutable, we allow (onetime) change from nil==> to value + if oldService.Spec.IPFamily != nil { + allErrs = append(allErrs, ValidateImmutableField(service.Spec.IPFamily, oldService.Spec.IPFamily, field.NewPath("spec", "ipFamily"))...) + } } allErrs = append(allErrs, ValidateService(service)...) diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index 55d43df50b6..fd10c767e4d 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -9134,6 +9134,7 @@ func TestValidatePodStatusUpdate(t *testing.T) { } func makeValidService() core.Service { + serviceIPFamily := core.IPv4Protocol return core.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "valid", @@ -9147,6 +9148,7 @@ func makeValidService() core.Service { SessionAffinity: "None", Type: core.ServiceTypeClusterIP, Ports: []core.ServicePort{{Name: "p", Protocol: "TCP", Port: 8675, TargetPort: intstr.FromInt(8675)}}, + IPFamily: &serviceIPFamily, }, } } @@ -10072,6 +10074,29 @@ func TestValidateService(t *testing.T) { }, numErrs: 1, }, + { + name: "valid, nil service IPFamily", + tweakSvc: func(s *core.Service) { + s.Spec.IPFamily = nil + }, + numErrs: 0, + }, + { + name: "valid, service with valid IPFamily", + tweakSvc: func(s *core.Service) { + ipv4Service := core.IPv4Protocol + s.Spec.IPFamily = &ipv4Service + }, + numErrs: 0, + }, + { + name: "invalid, service with invalid IPFamily", + tweakSvc: func(s *core.Service) { + invalidServiceIPFamily := core.IPFamily("not-a-valid-ip-family") + s.Spec.IPFamily = &invalidServiceIPFamily + }, + numErrs: 1, + }, } for _, tc := range testCases { @@ -11922,6 +11947,80 @@ func TestValidateServiceUpdate(t *testing.T) { }, numErrs: 1, }, + /* Service IP Family */ + { + name: "same ServiceIPFamily", + tweakSvc: func(oldSvc, newSvc *core.Service) { + ipv4Service := core.IPv4Protocol + oldSvc.Spec.Type = core.ServiceTypeClusterIP + oldSvc.Spec.IPFamily = &ipv4Service + + newSvc.Spec.Type = core.ServiceTypeClusterIP + newSvc.Spec.IPFamily = &ipv4Service + }, + numErrs: 0, + }, + { + name: "ExternalName while changing Service IPFamily", + tweakSvc: func(oldSvc, newSvc *core.Service) { + ipv4Service := core.IPv4Protocol + oldSvc.Spec.ExternalName = "somename" + oldSvc.Spec.Type = core.ServiceTypeExternalName + oldSvc.Spec.IPFamily = &ipv4Service + + ipv6Service := core.IPv6Protocol + newSvc.Spec.ExternalName = "somename" + newSvc.Spec.Type = core.ServiceTypeExternalName + newSvc.Spec.IPFamily = &ipv6Service + }, + numErrs: 0, + }, + { + name: "setting ipfamily from nil to v4", + tweakSvc: func(oldSvc, newSvc *core.Service) { + oldSvc.Spec.IPFamily = nil + + ipv4Service := core.IPv4Protocol + newSvc.Spec.ExternalName = "somename" + newSvc.Spec.IPFamily = &ipv4Service + }, + numErrs: 0, + }, + { + name: "setting ipfamily from nil to v6", + tweakSvc: func(oldSvc, newSvc *core.Service) { + oldSvc.Spec.IPFamily = nil + + ipv6Service := core.IPv6Protocol + newSvc.Spec.ExternalName = "somename" + newSvc.Spec.IPFamily = &ipv6Service + }, + numErrs: 0, + }, + { + name: "remove ipfamily", + tweakSvc: func(oldSvc, newSvc *core.Service) { + ipv6Service := core.IPv6Protocol + oldSvc.Spec.IPFamily = &ipv6Service + + newSvc.Spec.IPFamily = nil + }, + numErrs: 1, + }, + + { + name: "change ServiceIPFamily", + tweakSvc: func(oldSvc, newSvc *core.Service) { + ipv4Service := core.IPv4Protocol + oldSvc.Spec.Type = core.ServiceTypeClusterIP + oldSvc.Spec.IPFamily = &ipv4Service + + ipv6Service := core.IPv6Protocol + newSvc.Spec.Type = core.ServiceTypeClusterIP + newSvc.Spec.IPFamily = &ipv6Service + }, + numErrs: 1, + }, } for _, tc := range testCases { diff --git a/pkg/registry/core/service/strategy.go b/pkg/registry/core/service/strategy.go index 1955944604a..7327a4da21b 100644 --- a/pkg/registry/core/service/strategy.go +++ b/pkg/registry/core/service/strategy.go @@ -26,6 +26,9 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/validation" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" ) // svcStrategy implements behavior for Services @@ -114,6 +117,21 @@ func (svcStrategy) Export(ctx context.Context, obj runtime.Object, exact bool) e // newSvc.Spec.MyFeature = nil // } func dropServiceDisabledFields(newSvc *api.Service, oldSvc *api.Service) { + // Drop IPFamily if DualStack is not enabled + if !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) && !serviceIPFamilyInUse(oldSvc) { + newSvc.Spec.IPFamily = nil + } +} + +// returns true if svc.Spec.ServiceIPFamily field is in use +func serviceIPFamilyInUse(svc *api.Service) bool { + if svc == nil { + return false + } + if svc.Spec.IPFamily != nil { + return true + } + return false } type serviceStatusStrategy struct { diff --git a/pkg/registry/core/service/strategy_test.go b/pkg/registry/core/service/strategy_test.go index 1c5ac1d4308..cd9e08a7c53 100644 --- a/pkg/registry/core/service/strategy_test.go +++ b/pkg/registry/core/service/strategy_test.go @@ -23,11 +23,16 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/intstr" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/registry/rest" api "k8s.io/kubernetes/pkg/apis/core" _ "k8s.io/kubernetes/pkg/apis/core/install" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/kubernetes/pkg/features" ) func TestExportService(t *testing.T) { @@ -128,6 +133,7 @@ func TestCheckGeneratedNameError(t *testing.T) { } func makeValidService() api.Service { + defaultServiceIPFamily := api.IPv4Protocol return api.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "valid", @@ -141,6 +147,7 @@ func makeValidService() api.Service { SessionAffinity: "None", Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{{Name: "p", Protocol: "TCP", Port: 8675, TargetPort: intstr.FromInt(8675)}}, + IPFamily: &defaultServiceIPFamily, }, } } @@ -241,3 +248,70 @@ func TestServiceStatusStrategy(t *testing.T) { t.Errorf("Unexpected error %v", errs) } } + +func makeServiceWithIPFamily(IPFamily *api.IPFamily) *api.Service { + return &api.Service{ + Spec: api.ServiceSpec{ + IPFamily: IPFamily, + }, + } +} +func TestDropDisabledField(t *testing.T) { + ipv4Service := api.IPv4Protocol + ipv6Service := api.IPv6Protocol + testCases := []struct { + name string + enableDualStack bool + svc *api.Service + oldSvc *api.Service + compareSvc *api.Service + }{ + { + name: "not dual stack, field not used", + enableDualStack: false, + svc: makeServiceWithIPFamily(nil), + oldSvc: nil, + compareSvc: makeServiceWithIPFamily(nil), + }, + { + name: "not dual stack, field used in new, not in old", + enableDualStack: false, + svc: makeServiceWithIPFamily(&ipv4Service), + oldSvc: nil, + compareSvc: makeServiceWithIPFamily(nil), + }, + { + name: "not dual stack, field used in old and new", + enableDualStack: false, + svc: makeServiceWithIPFamily(&ipv4Service), + oldSvc: makeServiceWithIPFamily(&ipv4Service), + compareSvc: makeServiceWithIPFamily(&ipv4Service), + }, + { + name: "dualstack, field used", + enableDualStack: true, + svc: makeServiceWithIPFamily(&ipv6Service), + oldSvc: nil, + compareSvc: makeServiceWithIPFamily(&ipv6Service), + }, + + /* add more tests for other dropped fields as needed */ + } + for _, tc := range testCases { + func() { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.enableDualStack)() + old := tc.oldSvc.DeepCopy() + dropServiceDisabledFields(tc.svc, tc.oldSvc) + + // old node should never be changed + if !reflect.DeepEqual(tc.oldSvc, old) { + t.Errorf("%v: old svc changed: %v", tc.name, diff.ObjectReflectDiff(tc.oldSvc, old)) + } + + if !reflect.DeepEqual(tc.svc, tc.compareSvc) { + t.Errorf("%v: unexpected svc spec: %v", tc.name, diff.ObjectReflectDiff(tc.svc, tc.compareSvc)) + } + }() + } + +} diff --git a/staging/publishing/import-restrictions.yaml b/staging/publishing/import-restrictions.yaml index f66b33f292c..d033a68c983 100644 --- a/staging/publishing/import-restrictions.yaml +++ b/staging/publishing/import-restrictions.yaml @@ -9,6 +9,7 @@ - k8s.io/kubernetes/pkg/util - k8s.io/api/core/v1 - k8s.io/utils/pointer + - k8s.io/utils/net - k8s.io/klog # the following are temporary and should go away. Think twice (or more) before adding anything here. diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index b2e721e8895..9bf48ecf15c 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -3794,6 +3794,17 @@ type LoadBalancerIngress struct { Hostname string `json:"hostname,omitempty" protobuf:"bytes,2,opt,name=hostname"` } +// IPFamily represents the IP Family (IPv4 or IPv6). This type is used +// to express the family of an IP expressed by a type (i.e. service.Spec.IPFamily) +type IPFamily string + +const ( + // IPv4Protocol indicates that this IP is IPv4 protocol + IPv4Protocol IPFamily = "IPv4" + // IPv6Protocol indicates that this IP is IPv6 protocol + IPv6Protocol IPFamily = "IPv6" +) + // ServiceSpec describes the attributes that a user creates on a service. type ServiceSpec struct { // The list of ports that are exposed by this service. @@ -3909,6 +3920,16 @@ type ServiceSpec struct { // sessionAffinityConfig contains the configurations of session affinity. // +optional SessionAffinityConfig *SessionAffinityConfig `json:"sessionAffinityConfig,omitempty" protobuf:"bytes,14,opt,name=sessionAffinityConfig"` + + // ipFamily specifies whether this Service has a preference for a particular IP family (e.g. IPv4 vs. + // IPv6). If a specific IP family is requested, the clusterIP field will be allocated from that family, if it is + // available in the cluster. If no IP family is requested, the cluster's primary IP family will be used. + // Other IP fields (loadBalancerIP, loadBalancerSourceRanges, externalIPs) and controllers which + // allocate external load-balancers should use the same IP family. Endpoints for this Service will be of + // this family. This field is immutable after creation. Assigning a ServiceIPFamily not available in the + // cluster (e.g. IPv6 in IPv4 only cluster) is an error condition and will fail during clusterIP assignment. + // +optional + IPFamily *IPFamily `json:"ipFamily,omitempty" protobuf:"bytes,15,opt,name=ipFamily,Configcasttype=IPFamily"` } // ServicePort contains information on service's port. diff --git a/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe.go b/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe.go index a5c78c0da00..7ce165e2347 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe.go @@ -2478,6 +2478,11 @@ func describeService(service *corev1.Service, endpoints *corev1.Endpoints, event w.Write(LEVEL_0, "Selector:\t%s\n", labels.FormatLabels(service.Spec.Selector)) w.Write(LEVEL_0, "Type:\t%s\n", service.Spec.Type) w.Write(LEVEL_0, "IP:\t%s\n", service.Spec.ClusterIP) + + if service.Spec.IPFamily != nil { + w.Write(LEVEL_0, "IPFamily:\t%s\n", *(service.Spec.IPFamily)) + } + if len(service.Spec.ExternalIPs) > 0 { w.Write(LEVEL_0, "External IPs:\t%v\n", strings.Join(service.Spec.ExternalIPs, ",")) } diff --git a/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe_test.go b/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe_test.go index 1fe3b944f0a..66e719aba2a 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe_test.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/versioned/describe_test.go @@ -351,6 +351,8 @@ func getResourceList(cpu, memory string) corev1.ResourceList { } func TestDescribeService(t *testing.T) { + defaultServiceIPFamily := corev1.IPv4Protocol + testCases := []struct { name string service *corev1.Service @@ -364,7 +366,8 @@ func TestDescribeService(t *testing.T) { Namespace: "foo", }, Spec: corev1.ServiceSpec{ - Type: corev1.ServiceTypeLoadBalancer, + Type: corev1.ServiceTypeLoadBalancer, + IPFamily: &defaultServiceIPFamily, Ports: []corev1.ServicePort{{ Name: "port-tcp", Port: 8080, @@ -402,7 +405,8 @@ func TestDescribeService(t *testing.T) { Namespace: "foo", }, Spec: corev1.ServiceSpec{ - Type: corev1.ServiceTypeLoadBalancer, + Type: corev1.ServiceTypeLoadBalancer, + IPFamily: &defaultServiceIPFamily, Ports: []corev1.ServicePort{{ Name: "port-tcp", Port: 8080, @@ -432,6 +436,46 @@ func TestDescribeService(t *testing.T) { "HealthCheck NodePort", "32222", }, }, + { + name: "test-ServiceIPFamily", + service: &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Namespace: "foo", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + IPFamily: &defaultServiceIPFamily, + Ports: []corev1.ServicePort{{ + Name: "port-tcp", + Port: 8080, + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromString("targetPort"), + NodePort: 31111, + }}, + Selector: map[string]string{"blah": "heh"}, + ClusterIP: "1.2.3.4", + LoadBalancerIP: "5.6.7.8", + SessionAffinity: "None", + ExternalTrafficPolicy: "Local", + HealthCheckNodePort: 32222, + }, + }, + expect: []string{ + "Name", "bar", + "Namespace", "foo", + "Selector", "blah=heh", + "Type", "LoadBalancer", + "IP", "1.2.3.4", + "IPFamily", "IPv4", + "Port", "port-tcp", "8080/TCP", + "TargetPort", "targetPort/TCP", + "NodePort", "port-tcp", "31111/TCP", + "Session Affinity", "None", + "External Traffic Policy", "Local", + "HealthCheck NodePort", "32222", + }, + }, } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { From 93c06821e623fdfb5fd1988f850c3c35bcaf2a5f Mon Sep 17 00:00:00 2001 From: "Khaled Henidak(Kal)" Date: Mon, 19 Aug 2019 20:45:22 +0000 Subject: [PATCH 2/4] Phase 2: service and endpoint processing --- cmd/kube-apiserver/app/options/options.go | 19 +- .../app/options/options_test.go | 2 +- cmd/kube-apiserver/app/options/validation.go | 49 +- .../app/options/validation_test.go | 132 ++++ cmd/kube-apiserver/app/server.go | 64 +- cmd/kube-apiserver/app/testing/testserver.go | 3 +- .../endpoint/endpoints_controller.go | 48 +- .../endpoint/endpoints_controller_test.go | 276 +++++++- pkg/master/controller.go | 16 +- pkg/master/master.go | 8 + pkg/registry/core/rest/storage_core.go | 39 +- .../core/service/ipallocator/allocator.go | 1 + .../service/ipallocator/allocator_test.go | 6 + .../service/ipallocator/controller/repair.go | 160 ++++- .../ipallocator/controller/repair_test.go | 351 +++++++++- pkg/registry/core/service/storage/rest.go | 104 ++- .../core/service/storage/rest_test.go | 617 ++++++++++++++---- test/e2e_node/services/apiserver.go | 2 +- test/integration/etcd/server.go | 2 +- test/integration/examples/apiserver_test.go | 2 +- test/integration/framework/test_server.go | 2 +- 21 files changed, 1656 insertions(+), 247 deletions(-) create mode 100644 cmd/kube-apiserver/app/options/validation_test.go diff --git a/cmd/kube-apiserver/app/options/options.go b/cmd/kube-apiserver/app/options/options.go index ac7ccad2d3e..e15f1052c6b 100644 --- a/cmd/kube-apiserver/app/options/options.go +++ b/cmd/kube-apiserver/app/options/options.go @@ -56,10 +56,16 @@ type ServerRunOptions struct { KubeletConfig kubeletclient.KubeletClientConfig KubernetesServiceNodePort int MaxConnectionBytesPerSec int64 - ServiceClusterIPRange net.IPNet // TODO: make this a list - ServiceNodePortRange utilnet.PortRange - SSHKeyfile string - SSHUser string + // ServiceClusterIPRange is mapped to input provided by user + ServiceClusterIPRanges string + //PrimaryServiceClusterIPRange and SecondaryServiceClusterIPRange are the results + // of parsing ServiceClusterIPRange into actual values + PrimaryServiceClusterIPRange net.IPNet + SecondaryServiceClusterIPRange net.IPNet + + ServiceNodePortRange utilnet.PortRange + SSHKeyfile string + SSHUser string ProxyClientCertFile string ProxyClientKeyFile string @@ -114,7 +120,7 @@ func NewServerRunOptions() *ServerRunOptions { }, ServiceNodePortRange: kubeoptions.DefaultServiceNodePortRange, } - s.ServiceClusterIPRange = kubeoptions.DefaultServiceIPCIDR + s.ServiceClusterIPRanges = kubeoptions.DefaultServiceIPCIDR.String() // Overwrite the default for storage data format. s.Etcd.DefaultStorageMediaType = "application/vnd.kubernetes.protobuf" @@ -179,7 +185,8 @@ func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) { "of type NodePort, using this as the value of the port. If zero, the Kubernetes master "+ "service will be of type ClusterIP.") - fs.IPNetVar(&s.ServiceClusterIPRange, "service-cluster-ip-range", s.ServiceClusterIPRange, ""+ + // TODO (khenidak) change documentation as we move IPv6DualStack feature from ALPHA to BETA + fs.StringVar(&s.ServiceClusterIPRanges, "service-cluster-ip-range", s.ServiceClusterIPRanges, ""+ "A CIDR notation IP range from which to assign service cluster IPs. This must not "+ "overlap with any IP ranges assigned to nodes for pods.") diff --git a/cmd/kube-apiserver/app/options/options_test.go b/cmd/kube-apiserver/app/options/options_test.go index 9dfd1d25a76..d41d284aaf6 100644 --- a/cmd/kube-apiserver/app/options/options_test.go +++ b/cmd/kube-apiserver/app/options/options_test.go @@ -118,7 +118,7 @@ func TestAddFlags(t *testing.T) { // This is a snapshot of expected options parsed by args. expected := &ServerRunOptions{ ServiceNodePortRange: kubeoptions.DefaultServiceNodePortRange, - ServiceClusterIPRange: kubeoptions.DefaultServiceIPCIDR, + ServiceClusterIPRanges: kubeoptions.DefaultServiceIPCIDR.String(), MasterCount: 5, EndpointReconcilerType: string(reconcilers.LeaseEndpointReconcilerType), AllowPrivileged: false, diff --git a/cmd/kube-apiserver/app/options/validation.go b/cmd/kube-apiserver/app/options/validation.go index d0b1bd0ada9..ae87be5d213 100644 --- a/cmd/kube-apiserver/app/options/validation.go +++ b/cmd/kube-apiserver/app/options/validation.go @@ -19,26 +19,69 @@ package options import ( "errors" "fmt" + "net" + "strings" apiextensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver" utilfeature "k8s.io/apiserver/pkg/util/feature" aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/features" + netutils "k8s.io/utils/net" ) // TODO: Longer term we should read this from some config store, rather than a flag. +// validateClusterIPFlags is expected to be called after Complete() func validateClusterIPFlags(options *ServerRunOptions) []error { var errs []error - if options.ServiceClusterIPRange.IP == nil { - errs = append(errs, errors.New("no --service-cluster-ip-range specified")) + // validate that primary has been processed by user provided values or it has been defaulted + if options.PrimaryServiceClusterIPRange.IP == nil { + errs = append(errs, errors.New("--service-cluster-ip-range must contain at least one valid cidr")) } - var ones, bits = options.ServiceClusterIPRange.Mask.Size() + + serviceClusterIPRangeList := strings.Split(options.ServiceClusterIPRanges, ",") + if len(serviceClusterIPRangeList) > 2 { + errs = append(errs, errors.New("--service-cluster-ip-range must not contain more than two entries")) + } + + // Complete() expected to have set Primary* and Secondary* + // primary CIDR validation + var ones, bits = options.PrimaryServiceClusterIPRange.Mask.Size() if bits-ones > 20 { errs = append(errs, errors.New("specified --service-cluster-ip-range is too large")) } + // Secondary IP validation + secondaryServiceClusterIPRangeUsed := (options.SecondaryServiceClusterIPRange.IP != nil) + if secondaryServiceClusterIPRangeUsed && !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) { + errs = append(errs, fmt.Errorf("--secondary-service-cluster-ip-range can only be used if %v feature is enabled", string(features.IPv6DualStack))) + } + + // note: While the cluster might be dualstack (i.e. pods with multiple IPs), the user may choose + // to only ingress traffic within and into the cluster on one IP family only. this family is decided + // by the range set on --service-cluster-ip-range. If/when the user decides to use dual stack services + // the Secondary* must be of different IPFamily than --service-cluster-ip-range + if secondaryServiceClusterIPRangeUsed { + // Should be dualstack IPFamily(PrimaryServiceClusterIPRange) != IPFamily(SecondaryServiceClusterIPRange) + dualstack, err := netutils.IsDualStackCIDRs([]*net.IPNet{&options.PrimaryServiceClusterIPRange, &options.SecondaryServiceClusterIPRange}) + if err != nil { + errs = append(errs, errors.New("error attempting to validate dualstack for --service-cluster-ip-range and --secondary-service-cluster-ip-range")) + } + + if !dualstack { + errs = append(errs, errors.New("--service-cluster-ip-range and --secondary-service-cluster-ip-range must be of different IP family")) + } + + // should be smallish sized cidr, this thing is kept in etcd + // bigger cidr (specially those offered by IPv6) will add no value + // significantly increase snapshotting time. + var ones, bits = options.SecondaryServiceClusterIPRange.Mask.Size() + if bits-ones > 20 { + errs = append(errs, errors.New("specified --secondary-service-cluster-ip-range is too large")) + } + } + return errs } diff --git a/cmd/kube-apiserver/app/options/validation_test.go b/cmd/kube-apiserver/app/options/validation_test.go new file mode 100644 index 00000000000..535149fdd8b --- /dev/null +++ b/cmd/kube-apiserver/app/options/validation_test.go @@ -0,0 +1,132 @@ +/* +Copyright 2019 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package options + +import ( + "net" + "testing" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/kubernetes/pkg/features" +) + +func makeOptionsWithCIDRs(serviceCIDR string, secondaryServiceCIDR string) *ServerRunOptions { + value := serviceCIDR + if len(secondaryServiceCIDR) > 0 { + value = value + "," + secondaryServiceCIDR + } + + var primaryCIDR, secondaryCIDR net.IPNet + if len(serviceCIDR) > 0 { + _, cidr, _ := net.ParseCIDR(serviceCIDR) + if cidr != nil { + primaryCIDR = *(cidr) + } + } + + if len(secondaryServiceCIDR) > 0 { + _, cidr, _ := net.ParseCIDR(secondaryServiceCIDR) + if cidr != nil { + secondaryCIDR = *(cidr) + } + } + return &ServerRunOptions{ + ServiceClusterIPRanges: value, + PrimaryServiceClusterIPRange: primaryCIDR, + SecondaryServiceClusterIPRange: secondaryCIDR, + } +} + +func TestClusterSerivceIPRange(t *testing.T) { + testCases := []struct { + name string + options *ServerRunOptions + enableDualStack bool + expectErrors bool + }{ + { + name: "no service cidr", + expectErrors: true, + options: makeOptionsWithCIDRs("", ""), + enableDualStack: false, + }, + { + name: "only secondary service cidr, dual stack gate on", + expectErrors: true, + options: makeOptionsWithCIDRs("", "10.0.0.0/16"), + enableDualStack: true, + }, + { + name: "only secondary service cidr, dual stack gate off", + expectErrors: true, + options: makeOptionsWithCIDRs("", "10.0.0.0/16"), + enableDualStack: false, + }, + { + name: "primary and secondary are provided but not dual stack v4-v4", + expectErrors: true, + options: makeOptionsWithCIDRs("10.0.0.0/16", "11.0.0.0/16"), + enableDualStack: true, + }, + { + name: "primary and secondary are provided but not dual stack v6-v6", + expectErrors: true, + options: makeOptionsWithCIDRs("2000::/108", "3000::/108"), + enableDualStack: true, + }, + { + name: "valid dual stack with gate disabled", + expectErrors: true, + options: makeOptionsWithCIDRs("10.0.0.0/16", "3000::/108"), + enableDualStack: false, + }, + /* success cases */ + { + name: "valid primary", + expectErrors: false, + options: makeOptionsWithCIDRs("10.0.0.0/16", ""), + enableDualStack: false, + }, + { + name: "valid v4-v6 dual stack + gate on", + expectErrors: false, + options: makeOptionsWithCIDRs("10.0.0.0/16", "3000::/108"), + enableDualStack: true, + }, + { + name: "valid v6-v4 dual stack + gate on", + expectErrors: false, + options: makeOptionsWithCIDRs("3000::/108", "10.0.0.0/16"), + enableDualStack: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.enableDualStack)() + errs := validateClusterIPFlags(tc.options) + if len(errs) > 0 && !tc.expectErrors { + t.Errorf("expected no errors, errors found %+v", errs) + } + + if len(errs) == 0 && tc.expectErrors { + t.Errorf("expected errors, no errors found") + } + }) + } +} diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index b4b73cb863a..d64929577f8 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -306,11 +306,21 @@ func CreateKubeAPIServerConfig( PerConnectionBandwidthLimitBytesPerSec: s.MaxConnectionBytesPerSec, }) - serviceIPRange, apiServerServiceIP, lastErr := master.DefaultServiceIPRange(s.ServiceClusterIPRange) + serviceIPRange, apiServerServiceIP, lastErr := master.DefaultServiceIPRange(s.PrimaryServiceClusterIPRange) if lastErr != nil { return } + // defaults to empty range and ip + var secondaryServiceIPRange net.IPNet + // process secondary range only if provided by user + if s.SecondaryServiceClusterIPRange.IP != nil { + secondaryServiceIPRange, _, lastErr = master.DefaultServiceIPRange(s.SecondaryServiceClusterIPRange) + if lastErr != nil { + return + } + } + clientCA, lastErr := readCAorNil(s.Authentication.ClientCert.ClientCA) if lastErr != nil { return @@ -341,8 +351,10 @@ func CreateKubeAPIServerConfig( Tunneler: nodeTunneler, - ServiceIPRange: serviceIPRange, - APIServerServiceIP: apiServerServiceIP, + ServiceIPRange: serviceIPRange, + APIServerServiceIP: apiServerServiceIP, + SecondaryServiceIPRange: secondaryServiceIPRange, + APIServerServicePort: 443, ServiceNodePortRange: s.ServiceNodePortRange, @@ -548,11 +560,49 @@ func Complete(s *options.ServerRunOptions) (completedServerRunOptions, error) { if err := kubeoptions.DefaultAdvertiseAddress(s.GenericServerRunOptions, s.InsecureServing.DeprecatedInsecureServingOptions); err != nil { return options, err } - serviceIPRange, apiServerServiceIP, err := master.DefaultServiceIPRange(s.ServiceClusterIPRange) - if err != nil { - return options, fmt.Errorf("error determining service IP ranges: %v", err) + + // process s.ServiceClusterIPRange from list to Primary and Secondary + // we process secondary only if provided by user + + serviceClusterIPRangeList := strings.Split(s.ServiceClusterIPRanges, ",") + + var apiServerServiceIP net.IP + var serviceIPRange net.IPNet + var err error + // nothing provided by user, use default range (only applies to the Primary) + if len(serviceClusterIPRangeList) == 0 { + var primaryServiceClusterCIDR net.IPNet + serviceIPRange, apiServerServiceIP, err = master.DefaultServiceIPRange(primaryServiceClusterCIDR) + if err != nil { + return options, fmt.Errorf("error determining service IP ranges: %v", err) + } + s.PrimaryServiceClusterIPRange = serviceIPRange } - s.ServiceClusterIPRange = serviceIPRange + + if len(serviceClusterIPRangeList) > 0 { + _, primaryServiceClusterCIDR, err := net.ParseCIDR(serviceClusterIPRangeList[0]) + if err != nil { + return options, fmt.Errorf("service-cluster-ip-range[0] is not a valid cidr") + } + + serviceIPRange, apiServerServiceIP, err = master.DefaultServiceIPRange(*(primaryServiceClusterCIDR)) + if err != nil { + return options, fmt.Errorf("error determining service IP ranges for primary service cidr: %v", err) + } + s.PrimaryServiceClusterIPRange = serviceIPRange + } + + // user provided at least two entries + if len(serviceClusterIPRangeList) > 1 { + _, secondaryServiceClusterCIDR, err := net.ParseCIDR(serviceClusterIPRangeList[1]) + if err != nil { + return options, fmt.Errorf("service-cluster-ip-range[1] is not an ip net") + } + + s.SecondaryServiceClusterIPRange = *(secondaryServiceClusterCIDR) + } + //note: validation asserts that the list is max of two dual stack entries + if err := s.SecureServing.MaybeDefaultWithSelfSignedCerts(s.GenericServerRunOptions.AdvertiseAddress.String(), []string{"kubernetes.default.svc", "kubernetes.default", "kubernetes"}, []net.IP{apiServerServiceIP}); err != nil { return options, fmt.Errorf("error creating self-signed certificates: %v", err) } diff --git a/cmd/kube-apiserver/app/testing/testserver.go b/cmd/kube-apiserver/app/testing/testserver.go index 10b12c1b867..83139748257 100644 --- a/cmd/kube-apiserver/app/testing/testserver.go +++ b/cmd/kube-apiserver/app/testing/testserver.go @@ -133,8 +133,7 @@ func StartTestServer(t Logger, instanceOptions *TestServerInstanceOptions, custo } s.SecureServing.ServerCert.FixtureDirectory = path.Join(path.Dir(thisFile), "testdata") - s.ServiceClusterIPRange.IP = net.IPv4(10, 0, 0, 0) - s.ServiceClusterIPRange.Mask = net.CIDRMask(16, 32) + s.ServiceClusterIPRanges = "10.0.0.0/16" s.Etcd.StorageConfig = *storageConfig s.APIEnablement.RuntimeConfig.Set("api/all=true") diff --git a/pkg/controller/endpoint/endpoints_controller.go b/pkg/controller/endpoint/endpoints_controller.go index 907b4786721..54026c3df85 100644 --- a/pkg/controller/endpoint/endpoints_controller.go +++ b/pkg/controller/endpoint/endpoints_controller.go @@ -45,6 +45,10 @@ import ( api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/util/metrics" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" + utilnet "k8s.io/utils/net" ) const ( @@ -218,6 +222,37 @@ func (e *EndpointController) addPod(obj interface{}) { } } +func podToEndpointAddressForService(svc *v1.Service, pod *v1.Pod) (*v1.EndpointAddress, error) { + if !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) { + return podToEndpointAddress(pod), nil + } + + // api-server service controller ensured that the service got the correct IP Family + // according to user setup, here we only need to match EndPoint IPs' family to service + // actual IP family. as in, we don't need to check service.IPFamily + + ipv6ClusterIP := utilnet.IsIPv6String(svc.Spec.ClusterIP) + for _, podIP := range pod.Status.PodIPs { + ipv6PodIP := utilnet.IsIPv6String(podIP.IP) + // same family? + // TODO (khenidak) when we remove the max of 2 PodIP limit from pods + // we will have to return multiple endpoint addresses + if ipv6ClusterIP == ipv6PodIP { + return &v1.EndpointAddress{ + IP: podIP.IP, + NodeName: &pod.Spec.NodeName, + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: pod.ObjectMeta.Namespace, + Name: pod.ObjectMeta.Name, + UID: pod.ObjectMeta.UID, + ResourceVersion: pod.ObjectMeta.ResourceVersion, + }}, nil + } + } + return nil, fmt.Errorf("failed to find a matching endpoint for service %v", svc.Name) +} + func podToEndpointAddress(pod *v1.Pod) *v1.EndpointAddress { return &v1.EndpointAddress{ IP: pod.Status.PodIP, @@ -244,7 +279,9 @@ func podChanged(oldPod, newPod *v1.Pod) bool { return true } // Convert the pod to an EndpointAddress, clear inert fields, - // and see if they are the same. + // and see if they are the same. Even in a dual stack (multi pod IP) a pod + // will never change just one of its IPs, it will always change all. the below + // comparison to check if a pod has changed will still work newEndpointAddress := podToEndpointAddress(newPod) oldEndpointAddress := podToEndpointAddress(oldPod) // Ignore the ResourceVersion because it changes @@ -473,7 +510,14 @@ func (e *EndpointController) syncService(key string) error { continue } - epa := *podToEndpointAddress(pod) + ep, err := podToEndpointAddressForService(service, pod) + if err != nil { + // this will happen, if the cluster runs with some nodes configured as dual stack and some as not + // such as the case of an upgrade.. + klog.V(2).Infof("failed to find endpoint for service:%v with ClusterIP:%v on pod:%v with error:%v", service.Name, service.Spec.ClusterIP, pod.Name, err) + continue + } + epa := *ep hostname := pod.Spec.Hostname if len(hostname) > 0 && pod.Spec.Subdomain == service.Name && service.Namespace == pod.Namespace { diff --git a/pkg/controller/endpoint/endpoints_controller_test.go b/pkg/controller/endpoint/endpoints_controller_test.go index 6c919626b3e..77683115d0a 100644 --- a/pkg/controller/endpoint/endpoints_controller_test.go +++ b/pkg/controller/endpoint/endpoints_controller_test.go @@ -31,15 +31,18 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" + utilfeature "k8s.io/apiserver/pkg/util/feature" "k8s.io/client-go/informers" clientset "k8s.io/client-go/kubernetes" restclient "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" utiltesting "k8s.io/client-go/util/testing" + featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/kubernetes/pkg/api/testapi" endptspkg "k8s.io/kubernetes/pkg/api/v1/endpoints" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/controller" + "k8s.io/kubernetes/pkg/features" ) var alwaysReady = func() bool { return true } @@ -49,7 +52,7 @@ var triggerTime = time.Date(2018, 01, 01, 0, 0, 0, 0, time.UTC) var triggerTimeString = triggerTime.Format(time.RFC3339Nano) var oldTriggerTimeString = triggerTime.Add(-time.Hour).Format(time.RFC3339Nano) -func testPod(namespace string, id int, nPorts int, isReady bool) *v1.Pod { +func testPod(namespace string, id int, nPorts int, isReady bool, makeDualstack bool) *v1.Pod { p := &v1.Pod{ TypeMeta: metav1.TypeMeta{APIVersion: "v1"}, ObjectMeta: metav1.ObjectMeta{ @@ -77,14 +80,24 @@ func testPod(namespace string, id int, nPorts int, isReady bool) *v1.Pod { p.Spec.Containers[0].Ports = append(p.Spec.Containers[0].Ports, v1.ContainerPort{Name: fmt.Sprintf("port%d", j), ContainerPort: int32(8080 + j)}) } + if makeDualstack { + p.Status.PodIPs = []v1.PodIP{ + { + IP: p.Status.PodIP, + }, + { + IP: fmt.Sprintf("2000::%d", id), + }, + } + } return p } -func addPods(store cache.Store, namespace string, nPods int, nPorts int, nNotReady int) { +func addPods(store cache.Store, namespace string, nPods int, nPorts int, nNotReady int, makeDualstack bool) { for i := 0; i < nPods+nNotReady; i++ { isReady := i < nPods - pod := testPod(namespace, i, nPorts, isReady) + pod := testPod(namespace, i, nPorts, isReady, makeDualstack) store.Add(pod) } } @@ -289,7 +302,7 @@ func TestSyncEndpointsProtocolTCP(t *testing.T) { Ports: []v1.EndpointPort{{Port: 1000, Protocol: "TCP"}}, }}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -330,7 +343,7 @@ func TestSyncEndpointsProtocolUDP(t *testing.T) { Ports: []v1.EndpointPort{{Port: 1000, Protocol: "UDP"}}, }}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -371,7 +384,7 @@ func TestSyncEndpointsProtocolSCTP(t *testing.T) { Ports: []v1.EndpointPort{{Port: 1000, Protocol: "SCTP"}}, }}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -409,7 +422,7 @@ func TestSyncEndpointsItemsEmptySelectorSelectsAll(t *testing.T) { }, Subsets: []v1.EndpointSubset{}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -446,7 +459,7 @@ func TestSyncEndpointsItemsEmptySelectorSelectsAllNotReady(t *testing.T) { }, Subsets: []v1.EndpointSubset{}, }) - addPods(endpoints.podStore, ns, 0, 1, 1) + addPods(endpoints.podStore, ns, 0, 1, 1, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -483,7 +496,7 @@ func TestSyncEndpointsItemsEmptySelectorSelectsAllMixed(t *testing.T) { }, Subsets: []v1.EndpointSubset{}, }) - addPods(endpoints.podStore, ns, 1, 1, 1) + addPods(endpoints.podStore, ns, 1, 1, 1, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -524,7 +537,7 @@ func TestSyncEndpointsItemsPreexisting(t *testing.T) { Ports: []v1.EndpointPort{{Port: 1000}}, }}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -564,7 +577,7 @@ func TestSyncEndpointsItemsPreexistingIdentical(t *testing.T) { Ports: []v1.EndpointPort{{Port: 8080, Protocol: "TCP"}}, }}, }) - addPods(endpoints.podStore, metav1.NamespaceDefault, 1, 1, 0) + addPods(endpoints.podStore, metav1.NamespaceDefault, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{ @@ -581,8 +594,9 @@ func TestSyncEndpointsItems(t *testing.T) { testServer, endpointsHandler := makeTestServer(t, ns) defer testServer.Close() endpoints := newController(testServer.URL, 0*time.Second) - addPods(endpoints.podStore, ns, 3, 2, 0) - addPods(endpoints.podStore, "blah", 5, 2, 0) // make sure these aren't found! + addPods(endpoints.podStore, ns, 3, 2, 0, false) + addPods(endpoints.podStore, "blah", 5, 2, 0, false) // make sure these aren't found! + endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -622,7 +636,7 @@ func TestSyncEndpointsItemsWithLabels(t *testing.T) { testServer, endpointsHandler := makeTestServer(t, ns) defer testServer.Close() endpoints := newController(testServer.URL, 0*time.Second) - addPods(endpoints.podStore, ns, 3, 2, 0) + addPods(endpoints.podStore, ns, 3, 2, 0, false) serviceLabels := map[string]string{"foo": "bar"} endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{ @@ -682,7 +696,7 @@ func TestSyncEndpointsItemsPreexistingLabelsChange(t *testing.T) { Ports: []v1.EndpointPort{{Port: 1000}}, }}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) serviceLabels := map[string]string{"baz": "blah"} endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{ @@ -731,7 +745,8 @@ func TestWaitsForAllInformersToBeSynced2(t *testing.T) { testServer, endpointsHandler := makeTestServer(t, ns) defer testServer.Close() endpoints := newController(testServer.URL, 0*time.Second) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) + service := &v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -782,7 +797,7 @@ func TestSyncEndpointsHeadlessService(t *testing.T) { Ports: []v1.EndpointPort{{Port: 1000, Protocol: "TCP"}}, }}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -928,7 +943,7 @@ func TestSyncEndpointsHeadlessWithoutPort(t *testing.T) { Ports: nil, }, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.syncService(ns + "/foo") endpointsHandler.ValidateRequestCount(t, 1) data := runtime.EncodeOrDie(testapi.Default.Codec(), &v1.Endpoints{ @@ -1033,11 +1048,146 @@ func TestShouldPodBeInEndpoints(t *testing.T) { } } } +func TestPodToEndpointAddressForService(t *testing.T) { + testCases := []struct { + name string + expectedEndPointIP string + enableDualStack bool + expectError bool + enableDualStackPod bool + + service v1.Service + }{ + { + name: "v4 service, in a single stack cluster", + expectedEndPointIP: "1.2.3.4", + + enableDualStack: false, + expectError: false, + enableDualStackPod: false, + + service: v1.Service{ + Spec: v1.ServiceSpec{ + ClusterIP: "10.0.0.1", + }, + }, + }, + { + name: "v4 service, in a dual stack cluster", + + expectedEndPointIP: "1.2.3.4", + enableDualStack: true, + expectError: false, + enableDualStackPod: true, + + service: v1.Service{ + Spec: v1.ServiceSpec{ + ClusterIP: "10.0.0.1", + }, + }, + }, + { + name: "v6 service, in a dual stack cluster. dual stack enabled", + expectedEndPointIP: "2000::0", + + enableDualStack: true, + expectError: false, + enableDualStackPod: true, + + service: v1.Service{ + Spec: v1.ServiceSpec{ + ClusterIP: "3000::1", + }, + }, + }, + + // in reality this is a misconfigured cluster + // i.e user is not using dual stack and have PodIP == v4 and ServiceIP==v6 + // we are testing that we will keep producing the expected behavior + { + name: "v6 service, in a v4 only cluster. dual stack disabled", + expectedEndPointIP: "1.2.3.4", + + enableDualStack: false, + expectError: false, + enableDualStackPod: false, + + service: v1.Service{ + Spec: v1.ServiceSpec{ + ClusterIP: "3000::1", + }, + }, + }, + { + name: "v6 service, in a v4 only cluster - dual stack enabled", + expectedEndPointIP: "1.2.3.4", + + enableDualStack: true, + expectError: true, + enableDualStackPod: false, + + service: v1.Service{ + Spec: v1.ServiceSpec{ + ClusterIP: "3000::1", + }, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.enableDualStack)() + podStore := cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc) + ns := "test" + addPods(podStore, ns, 1, 1, 0, tc.enableDualStackPod) + pods := podStore.List() + if len(pods) != 1 { + t.Fatalf("podStore size: expected: %d, got: %d", 1, len(pods)) + } + pod := pods[0].(*v1.Pod) + epa, err := podToEndpointAddressForService(&tc.service, pod) + + if err != nil && !tc.expectError { + t.Fatalf("podToEndpointAddressForService returned unexpected error %v", err) + } + + if err == nil && tc.expectError { + t.Fatalf("podToEndpointAddressForService should have returned error but it did not") + } + + if err != nil && tc.expectError { + return + } + + if epa.IP != tc.expectedEndPointIP { + t.Fatalf("IP: expected: %s, got: %s", pod.Status.PodIP, epa.IP) + } + if *(epa.NodeName) != pod.Spec.NodeName { + t.Fatalf("NodeName: expected: %s, got: %s", pod.Spec.NodeName, *(epa.NodeName)) + } + if epa.TargetRef.Kind != "Pod" { + t.Fatalf("TargetRef.Kind: expected: %s, got: %s", "Pod", epa.TargetRef.Kind) + } + if epa.TargetRef.Namespace != pod.ObjectMeta.Namespace { + t.Fatalf("TargetRef.Kind: expected: %s, got: %s", pod.ObjectMeta.Namespace, epa.TargetRef.Namespace) + } + if epa.TargetRef.Name != pod.ObjectMeta.Name { + t.Fatalf("TargetRef.Kind: expected: %s, got: %s", pod.ObjectMeta.Name, epa.TargetRef.Name) + } + if epa.TargetRef.UID != pod.ObjectMeta.UID { + t.Fatalf("TargetRef.Kind: expected: %s, got: %s", pod.ObjectMeta.UID, epa.TargetRef.UID) + } + if epa.TargetRef.ResourceVersion != pod.ObjectMeta.ResourceVersion { + t.Fatalf("TargetRef.Kind: expected: %s, got: %s", pod.ObjectMeta.ResourceVersion, epa.TargetRef.ResourceVersion) + } + }) + } + +} func TestPodToEndpointAddress(t *testing.T) { podStore := cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc) ns := "test" - addPods(podStore, ns, 1, 1, 0) + addPods(podStore, ns, 1, 1, 0, false) pods := podStore.List() if len(pods) != 1 { t.Errorf("podStore size: expected: %d, got: %d", 1, len(pods)) @@ -1071,7 +1221,7 @@ func TestPodToEndpointAddress(t *testing.T) { func TestPodChanged(t *testing.T) { podStore := cache.NewStore(cache.DeletionHandlingMetaNamespaceKeyFunc) ns := "test" - addPods(podStore, ns, 1, 1, 0) + addPods(podStore, ns, 1, 1, 0, false) pods := podStore.List() if len(pods) != 1 { t.Errorf("podStore size: expected: %d, got: %d", 1, len(pods)) @@ -1102,6 +1252,80 @@ func TestPodChanged(t *testing.T) { } newPod.Status.PodIP = oldPod.Status.PodIP + /* dual stack tests */ + // primary changes, because changing IPs is done by changing sandbox + // case 1: add new secondrary IP + newPod.Status.PodIP = "1.1.3.1" + newPod.Status.PodIPs = []v1.PodIP{ + { + IP: "1.1.3.1", + }, + { + IP: "2000::1", + }, + } + if !podChanged(oldPod, newPod) { + t.Errorf("Expected pod to be changed with adding secondary IP") + } + // reset + newPod.Status.PodIPs = nil + newPod.Status.PodIP = oldPod.Status.PodIP + + // case 2: removing a secondary IP + saved := oldPod.Status.PodIP + oldPod.Status.PodIP = "1.1.3.1" + oldPod.Status.PodIPs = []v1.PodIP{ + { + IP: "1.1.3.1", + }, + { + IP: "2000::1", + }, + } + + newPod.Status.PodIP = "1.2.3.4" + newPod.Status.PodIPs = []v1.PodIP{ + { + IP: "1.2.3.4", + }, + } + + // reset + oldPod.Status.PodIPs = nil + newPod.Status.PodIPs = nil + oldPod.Status.PodIP = saved + newPod.Status.PodIP = saved + // case 3: change secondary + // case 2: removing a secondary IP + saved = oldPod.Status.PodIP + oldPod.Status.PodIP = "1.1.3.1" + oldPod.Status.PodIPs = []v1.PodIP{ + { + IP: "1.1.3.1", + }, + { + IP: "2000::1", + }, + } + + newPod.Status.PodIP = "1.2.3.4" + newPod.Status.PodIPs = []v1.PodIP{ + { + IP: "1.2.3.4", + }, + { + IP: "2000::2", + }, + } + + // reset + oldPod.Status.PodIPs = nil + newPod.Status.PodIPs = nil + oldPod.Status.PodIP = saved + newPod.Status.PodIP = saved + + /* end dual stack testing */ + newPod.ObjectMeta.Name = "wrong-name" if !podChanged(oldPod, newPod) { t.Errorf("Expected pod to be changed with pod name change") @@ -1203,7 +1427,7 @@ func TestLastTriggerChangeTimeAnnotation(t *testing.T) { Ports: []v1.EndpointPort{{Port: 1000, Protocol: "TCP"}}, }}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns, CreationTimestamp: metav1.NewTime(triggerTime)}, Spec: v1.ServiceSpec{ @@ -1250,7 +1474,7 @@ func TestLastTriggerChangeTimeAnnotation_AnnotationOverridden(t *testing.T) { Ports: []v1.EndpointPort{{Port: 1000, Protocol: "TCP"}}, }}, }) - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns, CreationTimestamp: metav1.NewTime(triggerTime)}, Spec: v1.ServiceSpec{ @@ -1298,7 +1522,7 @@ func TestLastTriggerChangeTimeAnnotation_AnnotationCleared(t *testing.T) { }}, }) // Neither pod nor service has trigger time, this should cause annotation to be cleared. - addPods(endpoints.podStore, ns, 1, 1, 0) + addPods(endpoints.podStore, ns, 1, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, Spec: v1.ServiceSpec{ @@ -1435,7 +1659,7 @@ func TestPodUpdatesBatching(t *testing.T) { go endpoints.Run(1, stopCh) - addPods(endpoints.podStore, ns, tc.podsCount, 1, 0) + addPods(endpoints.podStore, ns, tc.podsCount, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, @@ -1568,7 +1792,7 @@ func TestPodAddsBatching(t *testing.T) { for i, add := range tc.adds { time.Sleep(add.delay) - p := testPod(ns, i, 1, true) + p := testPod(ns, i, 1, true, false) endpoints.podStore.Add(p) endpoints.addPod(p) } @@ -1679,7 +1903,7 @@ func TestPodDeleteBatching(t *testing.T) { go endpoints.Run(1, stopCh) - addPods(endpoints.podStore, ns, tc.podsCount, 1, 0) + addPods(endpoints.podStore, ns, tc.podsCount, 1, 0, false) endpoints.serviceStore.Add(&v1.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, diff --git a/pkg/master/controller.go b/pkg/master/controller.go index 3e90b84f692..36307def915 100644 --- a/pkg/master/controller.go +++ b/pkg/master/controller.go @@ -55,9 +55,12 @@ type Controller struct { EventClient corev1client.EventsGetter healthClient rest.Interface - ServiceClusterIPRegistry rangeallocation.RangeRegistry + ServiceClusterIPRegistry rangeallocation.RangeRegistry + ServiceClusterIPRange net.IPNet + SecondaryServiceClusterIPRegistry rangeallocation.RangeRegistry + SecondaryServiceClusterIPRange net.IPNet + ServiceClusterIPInterval time.Duration - ServiceClusterIPRange net.IPNet ServiceNodePortRegistry rangeallocation.RangeRegistry ServiceNodePortInterval time.Duration @@ -106,8 +109,11 @@ func (c *completedConfig) NewBootstrapController(legacyRESTStorage corerest.Lega SystemNamespaces: systemNamespaces, SystemNamespacesInterval: 1 * time.Minute, - ServiceClusterIPRegistry: legacyRESTStorage.ServiceClusterIPAllocator, - ServiceClusterIPRange: c.ExtraConfig.ServiceIPRange, + ServiceClusterIPRegistry: legacyRESTStorage.ServiceClusterIPAllocator, + ServiceClusterIPRange: c.ExtraConfig.ServiceIPRange, + SecondaryServiceClusterIPRegistry: legacyRESTStorage.SecondaryServiceClusterIPAllocator, + SecondaryServiceClusterIPRange: c.ExtraConfig.SecondaryServiceIPRange, + ServiceClusterIPInterval: 3 * time.Minute, ServiceNodePortRegistry: legacyRESTStorage.ServiceNodePortAllocator, @@ -148,7 +154,7 @@ func (c *Controller) Start() { klog.Errorf("Unable to remove old endpoints from kubernetes service: %v", err) } - repairClusterIPs := servicecontroller.NewRepair(c.ServiceClusterIPInterval, c.ServiceClient, c.EventClient, &c.ServiceClusterIPRange, c.ServiceClusterIPRegistry) + repairClusterIPs := servicecontroller.NewRepair(c.ServiceClusterIPInterval, c.ServiceClient, c.EventClient, &c.ServiceClusterIPRange, c.ServiceClusterIPRegistry, &c.SecondaryServiceClusterIPRange, c.SecondaryServiceClusterIPRegistry) repairNodePorts := portallocatorcontroller.NewRepair(c.ServiceNodePortInterval, c.ServiceClient, c.EventClient, c.ServiceNodePortRange, c.ServiceNodePortRegistry) // run all of the controllers once prior to returning from Start. diff --git a/pkg/master/master.go b/pkg/master/master.go index 9806579334a..9443f647ec8 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -132,6 +132,13 @@ type ExtraConfig struct { ServiceIPRange net.IPNet // The IP address for the GenericAPIServer service (must be inside ServiceIPRange) APIServerServiceIP net.IP + + // dual stack services, the range represents an alternative IP range for service IP + // must be of different family than primary (ServiceIPRange) + SecondaryServiceIPRange net.IPNet + // the secondary IP address the GenericAPIServer service (must be inside SecondaryServiceIPRange) + SecondaryAPIServerServiceIP net.IP + // Port for the apiserver service. APIServerServicePort int @@ -323,6 +330,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) KubeletClientConfig: c.ExtraConfig.KubeletClientConfig, EventTTL: c.ExtraConfig.EventTTL, ServiceIPRange: c.ExtraConfig.ServiceIPRange, + SecondaryServiceIPRange: c.ExtraConfig.SecondaryServiceIPRange, ServiceNodePortRange: c.ExtraConfig.ServiceNodePortRange, LoopbackClientConfig: c.GenericConfig.LoopbackClientConfig, ServiceAccountIssuer: c.ExtraConfig.ServiceAccountIssuer, diff --git a/pkg/registry/core/rest/storage_core.go b/pkg/registry/core/rest/storage_core.go index 6a00feae183..9ece81f5602 100644 --- a/pkg/registry/core/rest/storage_core.go +++ b/pkg/registry/core/rest/storage_core.go @@ -77,8 +77,10 @@ type LegacyRESTStorageProvider struct { EventTTL time.Duration // ServiceIPRange is used to build cluster IPs for discovery. - ServiceIPRange net.IPNet - ServiceNodePortRange utilnet.PortRange + ServiceIPRange net.IPNet + // allocates ips for secondary service cidr in dual stack clusters + SecondaryServiceIPRange net.IPNet + ServiceNodePortRange utilnet.PortRange ServiceAccountIssuer serviceaccount.TokenGenerator ServiceAccountMaxExpiration time.Duration @@ -92,8 +94,9 @@ type LegacyRESTStorageProvider struct { // master.go for wiring controllers. // TODO remove this by running the controller as a poststarthook type LegacyRESTStorage struct { - ServiceClusterIPAllocator rangeallocation.RangeRegistry - ServiceNodePortAllocator rangeallocation.RangeRegistry + ServiceClusterIPAllocator rangeallocation.RangeRegistry + SecondaryServiceClusterIPAllocator rangeallocation.RangeRegistry + ServiceNodePortAllocator rangeallocation.RangeRegistry } func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generic.RESTOptionsGetter) (LegacyRESTStorage, genericapiserver.APIGroupInfo, error) { @@ -216,6 +219,26 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generi } restStorage.ServiceClusterIPAllocator = serviceClusterIPRegistry + // allocator for secondary service ip range + var secondaryServiceClusterIPAllocator ipallocator.Interface + if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) && c.SecondaryServiceIPRange.IP != nil { + var secondaryServiceClusterIPRegistry rangeallocation.RangeRegistry + secondaryServiceClusterIPAllocator, err = ipallocator.NewAllocatorCIDRRange(&c.SecondaryServiceIPRange, func(max int, rangeSpec string) (allocator.Interface, error) { + mem := allocator.NewAllocationMap(max, rangeSpec) + // TODO etcdallocator package to return a storage interface via the storageFactory + etcd, err := serviceallocator.NewEtcd(mem, "/ranges/secondaryserviceips", api.Resource("serviceipallocations"), serviceStorageConfig) + if err != nil { + return nil, err + } + secondaryServiceClusterIPRegistry = etcd + return etcd, nil + }) + if err != nil { + return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, fmt.Errorf("cannot create cluster secondary IP allocator: %v", err) + } + restStorage.SecondaryServiceClusterIPAllocator = secondaryServiceClusterIPRegistry + } + var serviceNodePortRegistry rangeallocation.RangeRegistry serviceNodePortAllocator, err := portallocator.NewPortAllocatorCustom(c.ServiceNodePortRange, func(max int, rangeSpec string) (allocator.Interface, error) { mem := allocator.NewAllocationMap(max, rangeSpec) @@ -237,7 +260,13 @@ func (c LegacyRESTStorageProvider) NewLegacyRESTStorage(restOptionsGetter generi return LegacyRESTStorage{}, genericapiserver.APIGroupInfo{}, err } - serviceRest, serviceRestProxy := servicestore.NewREST(serviceRESTStorage, endpointsStorage, podStorage.Pod, serviceClusterIPAllocator, serviceNodePortAllocator, c.ProxyTransport) + serviceRest, serviceRestProxy := servicestore.NewREST(serviceRESTStorage, + endpointsStorage, + podStorage.Pod, + serviceClusterIPAllocator, + secondaryServiceClusterIPAllocator, + serviceNodePortAllocator, + c.ProxyTransport) restStorageMap := map[string]rest.Storage{ "pods": podStorage.Pod, diff --git a/pkg/registry/core/service/ipallocator/allocator.go b/pkg/registry/core/service/ipallocator/allocator.go index 37c5741078e..722d299683c 100644 --- a/pkg/registry/core/service/ipallocator/allocator.go +++ b/pkg/registry/core/service/ipallocator/allocator.go @@ -32,6 +32,7 @@ type Interface interface { AllocateNext() (net.IP, error) Release(net.IP) error ForEach(func(net.IP)) + CIDR() net.IPNet // For testing Has(ip net.IP) bool diff --git a/pkg/registry/core/service/ipallocator/allocator_test.go b/pkg/registry/core/service/ipallocator/allocator_test.go index 5174ef6fcd0..e821a6a1016 100644 --- a/pkg/registry/core/service/ipallocator/allocator_test.go +++ b/pkg/registry/core/service/ipallocator/allocator_test.go @@ -69,6 +69,12 @@ func TestAllocate(t *testing.T) { if f := r.Free(); f != tc.free { t.Errorf("Test %s unexpected free %d", tc.name, f) } + + rCIDR := r.CIDR() + if rCIDR.String() != tc.cidr { + t.Errorf("allocator returned a different cidr") + } + if f := r.Used(); f != 0 { t.Errorf("Test %s unexpected used %d", tc.name, f) } diff --git a/pkg/registry/core/service/ipallocator/controller/repair.go b/pkg/registry/core/service/ipallocator/controller/repair.go index b2cb50d8136..e89af254121 100644 --- a/pkg/registry/core/service/ipallocator/controller/repair.go +++ b/pkg/registry/core/service/ipallocator/controller/repair.go @@ -34,6 +34,10 @@ import ( "k8s.io/kubernetes/pkg/apis/core/v1/helper" "k8s.io/kubernetes/pkg/registry/core/rangeallocation" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" + netutil "k8s.io/utils/net" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" ) // Repair is a controller loop that periodically examines all service ClusterIP allocations @@ -54,10 +58,14 @@ import ( type Repair struct { interval time.Duration serviceClient corev1client.ServicesGetter - network *net.IPNet - alloc rangeallocation.RangeRegistry - leaks map[string]int // counter per leaked IP - recorder record.EventRecorder + + network *net.IPNet + alloc rangeallocation.RangeRegistry + secondaryNetwork *net.IPNet + secondaryAlloc rangeallocation.RangeRegistry + + leaks map[string]int // counter per leaked IP + recorder record.EventRecorder } // How many times we need to detect a leak before we clean up. This is to @@ -66,7 +74,7 @@ const numRepairsBeforeLeakCleanup = 3 // NewRepair creates a controller that periodically ensures that all clusterIPs are uniquely allocated across the cluster // and generates informational warnings for a cluster that is not in sync. -func NewRepair(interval time.Duration, serviceClient corev1client.ServicesGetter, eventClient corev1client.EventsGetter, network *net.IPNet, alloc rangeallocation.RangeRegistry) *Repair { +func NewRepair(interval time.Duration, serviceClient corev1client.ServicesGetter, eventClient corev1client.EventsGetter, network *net.IPNet, alloc rangeallocation.RangeRegistry, secondaryNetwork *net.IPNet, secondaryAlloc rangeallocation.RangeRegistry) *Repair { eventBroadcaster := record.NewBroadcaster() eventBroadcaster.StartRecordingToSink(&corev1client.EventSinkImpl{Interface: eventClient.Events("")}) recorder := eventBroadcaster.NewRecorder(legacyscheme.Scheme, v1.EventSource{Component: "ipallocator-repair-controller"}) @@ -74,10 +82,14 @@ func NewRepair(interval time.Duration, serviceClient corev1client.ServicesGetter return &Repair{ interval: interval, serviceClient: serviceClient, - network: network, - alloc: alloc, - leaks: map[string]int{}, - recorder: recorder, + + network: network, + alloc: alloc, + secondaryNetwork: secondaryNetwork, + secondaryAlloc: secondaryAlloc, + + leaks: map[string]int{}, + recorder: recorder, } } @@ -95,6 +107,29 @@ func (c *Repair) RunOnce() error { return retry.RetryOnConflict(retry.DefaultBackoff, c.runOnce) } +// selectAllocForIP returns an allocator for an IP based weather it belongs to the primary or the secondary allocator +func (c *Repair) selectAllocForIP(ip net.IP, primary ipallocator.Interface, secondary ipallocator.Interface) ipallocator.Interface { + if !c.shouldWorkOnSecondary() { + return primary + } + + cidr := secondary.CIDR() + if netutil.IsIPv6CIDR(&cidr) && netutil.IsIPv6(ip) { + return secondary + } + + return primary +} + +// shouldWorkOnSecondary returns true if the repairer should perform work for secondary network (dual stack) +func (c *Repair) shouldWorkOnSecondary() bool { + if !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) { + return false + } + + return c.secondaryNetwork != nil && c.secondaryNetwork.IP != nil +} + // runOnce verifies the state of the cluster IP allocations and returns an error if an unrecoverable problem occurs. func (c *Repair) runOnce() error { // TODO: (per smarterclayton) if Get() or ListServices() is a weak consistency read, @@ -107,10 +142,26 @@ func (c *Repair) runOnce() error { // If etcd server is not running we should wait for some time and fail only then. This is particularly // important when we start apiserver and etcd at the same time. var snapshot *api.RangeAllocation - err := wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { + var secondarySnapshot *api.RangeAllocation + + var stored, secondaryStored ipallocator.Interface + var err, secondaryErr error + + err = wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { var err error snapshot, err = c.alloc.Get() - return err == nil, err + if err != nil { + return false, err + } + + if c.shouldWorkOnSecondary() { + secondarySnapshot, err = c.secondaryAlloc.Get() + if err != nil { + return false, err + } + } + + return true, nil }) if err != nil { return fmt.Errorf("unable to refresh the service IP block: %v", err) @@ -119,10 +170,19 @@ func (c *Repair) runOnce() error { if snapshot.Range == "" { snapshot.Range = c.network.String() } + + if c.shouldWorkOnSecondary() && secondarySnapshot.Range == "" { + secondarySnapshot.Range = c.secondaryNetwork.String() + } // Create an allocator because it is easy to use. - stored, err := ipallocator.NewFromSnapshot(snapshot) - if err != nil { - return fmt.Errorf("unable to rebuild allocator from snapshot: %v", err) + + stored, err = ipallocator.NewFromSnapshot(snapshot) + if c.shouldWorkOnSecondary() { + secondaryStored, secondaryErr = ipallocator.NewFromSnapshot(secondarySnapshot) + } + + if err != nil || secondaryErr != nil { + return fmt.Errorf("unable to rebuild allocator from snapshots: %v", err) } // We explicitly send no resource version, since the resource version @@ -135,10 +195,20 @@ func (c *Repair) runOnce() error { return fmt.Errorf("unable to refresh the service IP block: %v", err) } - rebuilt, err := ipallocator.NewCIDRRange(c.network) + var rebuilt, secondaryRebuilt *ipallocator.Range + rebuilt, err = ipallocator.NewCIDRRange(c.network) if err != nil { return fmt.Errorf("unable to create CIDR range: %v", err) } + + if c.shouldWorkOnSecondary() { + secondaryRebuilt, err = ipallocator.NewCIDRRange(c.secondaryNetwork) + } + + if err != nil { + return fmt.Errorf("unable to create CIDR range: %v", err) + } + // Check every Service's ClusterIP, and rebuild the state as we think it should be. for _, svc := range list.Items { if !helper.IsServiceIPSet(&svc) { @@ -152,12 +222,15 @@ func (c *Repair) runOnce() error { runtime.HandleError(fmt.Errorf("the cluster IP %s for service %s/%s is not a valid IP; please recreate", svc.Spec.ClusterIP, svc.Name, svc.Namespace)) continue } + // mark it as in-use - switch err := rebuilt.Allocate(ip); err { + actualAlloc := c.selectAllocForIP(ip, rebuilt, secondaryRebuilt) + switch err := actualAlloc.Allocate(ip); err { case nil: - if stored.Has(ip) { + actualStored := c.selectAllocForIP(ip, stored, secondaryStored) + if actualStored.Has(ip) { // remove it from the old set, so we can find leaks - stored.Release(ip) + actualStored.Release(ip) } else { // cluster IP doesn't seem to be allocated c.recorder.Eventf(&svc, v1.EventTypeWarning, "ClusterIPNotAllocated", "Cluster IP %s is not allocated; repairing", ip) @@ -174,14 +247,50 @@ func (c *Repair) runOnce() error { runtime.HandleError(fmt.Errorf("the cluster IP %s for service %s/%s is not within the service CIDR %s; please recreate", ip, svc.Name, svc.Namespace, c.network)) case ipallocator.ErrFull: // somehow we are out of IPs - c.recorder.Eventf(&svc, v1.EventTypeWarning, "ServiceCIDRFull", "Service CIDR %s is full; you must widen the CIDR in order to create new services", c.network) - return fmt.Errorf("the service CIDR %s is full; you must widen the CIDR in order to create new services", c.network) + cidr := actualAlloc.CIDR() + c.recorder.Eventf(&svc, v1.EventTypeWarning, "ServiceCIDRFull", "Service CIDR %v is full; you must widen the CIDR in order to create new services", cidr) + return fmt.Errorf("the service CIDR %v is full; you must widen the CIDR in order to create new services", cidr) default: c.recorder.Eventf(&svc, v1.EventTypeWarning, "UnknownError", "Unable to allocate cluster IP %s due to an unknown error", ip) return fmt.Errorf("unable to allocate cluster IP %s for service %s/%s due to an unknown error, exiting: %v", ip, svc.Name, svc.Namespace, err) } } + c.checkLeaked(stored, rebuilt) + if c.shouldWorkOnSecondary() { + c.checkLeaked(secondaryStored, secondaryRebuilt) + } + + // Blast the rebuilt state into storage. + err = c.saveSnapShot(rebuilt, c.alloc, snapshot) + if err != nil { + return err + } + + if c.shouldWorkOnSecondary() { + err := c.saveSnapShot(secondaryRebuilt, c.secondaryAlloc, secondarySnapshot) + if err != nil { + return nil + } + } + return nil +} + +func (c *Repair) saveSnapShot(rebuilt *ipallocator.Range, alloc rangeallocation.RangeRegistry, snapshot *api.RangeAllocation) error { + if err := rebuilt.Snapshot(snapshot); err != nil { + return fmt.Errorf("unable to snapshot the updated service IP allocations: %v", err) + } + if err := alloc.CreateOrUpdate(snapshot); err != nil { + if errors.IsConflict(err) { + return err + } + return fmt.Errorf("unable to persist the updated service IP allocations: %v", err) + } + + return nil +} + +func (c *Repair) checkLeaked(stored ipallocator.Interface, rebuilt *ipallocator.Range) { // Check for IPs that are left in the old set. They appear to have been leaked. stored.ForEach(func(ip net.IP) { count, found := c.leaks[ip.String()] @@ -203,15 +312,4 @@ func (c *Repair) runOnce() error { } }) - // Blast the rebuilt state into storage. - if err := rebuilt.Snapshot(snapshot); err != nil { - return fmt.Errorf("unable to snapshot the updated service IP allocations: %v", err) - } - if err := c.alloc.CreateOrUpdate(snapshot); err != nil { - if errors.IsConflict(err) { - return err - } - return fmt.Errorf("unable to persist the updated service IP allocations: %v", err) - } - return nil } diff --git a/pkg/registry/core/service/ipallocator/controller/repair_test.go b/pkg/registry/core/service/ipallocator/controller/repair_test.go index 26992176f6c..1b24bde17c0 100644 --- a/pkg/registry/core/service/ipallocator/controller/repair_test.go +++ b/pkg/registry/core/service/ipallocator/controller/repair_test.go @@ -27,6 +27,10 @@ import ( "k8s.io/client-go/kubernetes/fake" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/kubernetes/pkg/features" ) type mockRangeRegistry struct { @@ -56,7 +60,7 @@ func TestRepair(t *testing.T) { item: &api.RangeAllocation{Range: "192.168.1.0/24"}, } _, cidr, _ := net.ParseCIDR(ipregistry.item.Range) - r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry) + r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry, nil, nil) if err := r.RunOnce(); err != nil { t.Fatal(err) @@ -69,7 +73,7 @@ func TestRepair(t *testing.T) { item: &api.RangeAllocation{Range: "192.168.1.0/24"}, updateErr: fmt.Errorf("test error"), } - r = NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry) + r = NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry, nil, nil) if err := r.RunOnce(); !strings.Contains(err.Error(), ": test error") { t.Fatal(err) } @@ -100,7 +104,7 @@ func TestRepairLeak(t *testing.T) { }, } - r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry) + r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry, nil, nil) // Run through the "leak detection holdoff" loops. for i := 0; i < (numRepairsBeforeLeakCleanup - 1); i++ { if err := r.RunOnce(); err != nil { @@ -176,7 +180,7 @@ func TestRepairWithExisting(t *testing.T) { Data: dst.Data, }, } - r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry) + r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry, nil, nil) if err := r.RunOnce(); err != nil { t.Fatal(err) } @@ -191,3 +195,342 @@ func TestRepairWithExisting(t *testing.T) { t.Errorf("unexpected ipallocator state: %d free", free) } } + +func makeRangeRegistry(t *testing.T, cidrRange string) *mockRangeRegistry { + _, cidr, _ := net.ParseCIDR(cidrRange) + previous, err := ipallocator.NewCIDRRange(cidr) + if err != nil { + t.Fatal(err) + } + + var dst api.RangeAllocation + err = previous.Snapshot(&dst) + if err != nil { + t.Fatal(err) + } + + return &mockRangeRegistry{ + item: &api.RangeAllocation{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "1", + }, + Range: dst.Range, + Data: dst.Data, + }, + } +} + +func makeFakeClientSet() *fake.Clientset { + return fake.NewSimpleClientset() +} +func makeIPNet(cidr string) *net.IPNet { + _, net, _ := net.ParseCIDR(cidr) + return net +} +func TestShouldWorkOnSecondary(t *testing.T) { + testCases := []struct { + name string + enableDualStack bool + expectedResult bool + primaryNet *net.IPNet + secondaryNet *net.IPNet + }{ + { + name: "not a dual stack, primary only", + enableDualStack: false, + expectedResult: false, + primaryNet: makeIPNet("10.0.0.0/16"), + secondaryNet: nil, + }, + { + name: "not a dual stack, primary and secondary provided", + enableDualStack: false, + expectedResult: false, + primaryNet: makeIPNet("10.0.0.0/16"), + secondaryNet: makeIPNet("2000::/120"), + }, + { + name: "dual stack, primary only", + enableDualStack: true, + expectedResult: false, + primaryNet: makeIPNet("10.0.0.0/16"), + secondaryNet: nil, + }, + { + name: "dual stack, primary and secondary", + enableDualStack: true, + expectedResult: true, + primaryNet: makeIPNet("10.0.0.0/16"), + secondaryNet: makeIPNet("2000::/120"), + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.enableDualStack)() + + fakeClient := makeFakeClientSet() + primaryRegistry := makeRangeRegistry(t, tc.primaryNet.String()) + var secondaryRegistery *mockRangeRegistry + + if tc.secondaryNet != nil { + secondaryRegistery = makeRangeRegistry(t, tc.secondaryNet.String()) + } + + repair := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), tc.primaryNet, primaryRegistry, tc.secondaryNet, secondaryRegistery) + if repair.shouldWorkOnSecondary() != tc.expectedResult { + t.Errorf("shouldWorkOnSecondary should be %v and found %v", tc.expectedResult, repair.shouldWorkOnSecondary()) + } + }) + } +} + +func TestRepairDualStack(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, true)() + + fakeClient := fake.NewSimpleClientset() + ipregistry := &mockRangeRegistry{ + item: &api.RangeAllocation{Range: "192.168.1.0/24"}, + } + secondaryIPRegistry := &mockRangeRegistry{ + item: &api.RangeAllocation{Range: "2000::/108"}, + } + + _, cidr, _ := net.ParseCIDR(ipregistry.item.Range) + _, secondaryCIDR, _ := net.ParseCIDR(secondaryIPRegistry.item.Range) + r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry, secondaryCIDR, secondaryIPRegistry) + + if err := r.RunOnce(); err != nil { + t.Fatal(err) + } + if !ipregistry.updateCalled || ipregistry.updated == nil || ipregistry.updated.Range != cidr.String() || ipregistry.updated != ipregistry.item { + t.Errorf("unexpected ipregistry: %#v", ipregistry) + } + if !secondaryIPRegistry.updateCalled || secondaryIPRegistry.updated == nil || secondaryIPRegistry.updated.Range != secondaryCIDR.String() || secondaryIPRegistry.updated != secondaryIPRegistry.item { + t.Errorf("unexpected ipregistry: %#v", ipregistry) + } + + ipregistry = &mockRangeRegistry{ + item: &api.RangeAllocation{Range: "192.168.1.0/24"}, + updateErr: fmt.Errorf("test error"), + } + secondaryIPRegistry = &mockRangeRegistry{ + item: &api.RangeAllocation{Range: "2000::/108"}, + updateErr: fmt.Errorf("test error"), + } + + r = NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry, secondaryCIDR, secondaryIPRegistry) + if err := r.RunOnce(); !strings.Contains(err.Error(), ": test error") { + t.Fatal(err) + } +} + +func TestRepairLeakDualStack(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, true)() + + _, cidr, _ := net.ParseCIDR("192.168.1.0/24") + previous, err := ipallocator.NewCIDRRange(cidr) + if err != nil { + t.Fatal(err) + } + + previous.Allocate(net.ParseIP("192.168.1.10")) + + _, secondaryCIDR, _ := net.ParseCIDR("2000::/108") + secondaryPrevious, err := ipallocator.NewCIDRRange(secondaryCIDR) + if err != nil { + t.Fatal(err) + } + secondaryPrevious.Allocate(net.ParseIP("2000::1")) + + var dst api.RangeAllocation + err = previous.Snapshot(&dst) + if err != nil { + t.Fatal(err) + } + + var secondaryDST api.RangeAllocation + err = secondaryPrevious.Snapshot(&secondaryDST) + if err != nil { + t.Fatal(err) + } + + fakeClient := fake.NewSimpleClientset() + + ipregistry := &mockRangeRegistry{ + item: &api.RangeAllocation{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "1", + }, + Range: dst.Range, + Data: dst.Data, + }, + } + secondaryIPRegistry := &mockRangeRegistry{ + item: &api.RangeAllocation{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "1", + }, + Range: secondaryDST.Range, + Data: secondaryDST.Data, + }, + } + + r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry, secondaryCIDR, secondaryIPRegistry) + // Run through the "leak detection holdoff" loops. + for i := 0; i < (numRepairsBeforeLeakCleanup - 1); i++ { + if err := r.RunOnce(); err != nil { + t.Fatal(err) + } + after, err := ipallocator.NewFromSnapshot(ipregistry.updated) + if err != nil { + t.Fatal(err) + } + if !after.Has(net.ParseIP("192.168.1.10")) { + t.Errorf("expected ipallocator to still have leaked IP") + } + secondaryAfter, err := ipallocator.NewFromSnapshot(secondaryIPRegistry.updated) + if err != nil { + t.Fatal(err) + } + if !secondaryAfter.Has(net.ParseIP("2000::1")) { + t.Errorf("expected ipallocator to still have leaked IP") + } + } + // Run one more time to actually remove the leak. + if err := r.RunOnce(); err != nil { + t.Fatal(err) + } + + after, err := ipallocator.NewFromSnapshot(ipregistry.updated) + if err != nil { + t.Fatal(err) + } + if after.Has(net.ParseIP("192.168.1.10")) { + t.Errorf("expected ipallocator to not have leaked IP") + } + secondaryAfter, err := ipallocator.NewFromSnapshot(secondaryIPRegistry.updated) + if err != nil { + t.Fatal(err) + } + if secondaryAfter.Has(net.ParseIP("2000::1")) { + t.Errorf("expected ipallocator to not have leaked IP") + } +} + +func TestRepairWithExistingDualStack(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, true)() + _, cidr, _ := net.ParseCIDR("192.168.1.0/24") + previous, err := ipallocator.NewCIDRRange(cidr) + if err != nil { + t.Fatal(err) + } + + _, secondaryCIDR, _ := net.ParseCIDR("2000::/108") + secondaryPrevious, err := ipallocator.NewCIDRRange(secondaryCIDR) + if err != nil { + t.Fatal(err) + } + + var dst api.RangeAllocation + err = previous.Snapshot(&dst) + if err != nil { + t.Fatal(err) + } + + var secondaryDST api.RangeAllocation + err = secondaryPrevious.Snapshot(&secondaryDST) + if err != nil { + t.Fatal(err) + } + + fakeClient := fake.NewSimpleClientset( + &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{Namespace: "one", Name: "one"}, + Spec: corev1.ServiceSpec{ClusterIP: "192.168.1.1"}, + }, + &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{Namespace: "one", Name: "one-v6"}, + Spec: corev1.ServiceSpec{ClusterIP: "2000::1"}, + }, + &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{Namespace: "two", Name: "two"}, + Spec: corev1.ServiceSpec{ClusterIP: "192.168.1.100"}, + }, + &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{Namespace: "two", Name: "two-6"}, + Spec: corev1.ServiceSpec{ClusterIP: "2000::2"}, + }, + &corev1.Service{ // outside CIDR, will be dropped + ObjectMeta: metav1.ObjectMeta{Namespace: "three", Name: "three"}, + Spec: corev1.ServiceSpec{ClusterIP: "192.168.0.1"}, + }, + &corev1.Service{ // outside CIDR, will be dropped + ObjectMeta: metav1.ObjectMeta{Namespace: "three", Name: "three-v6"}, + Spec: corev1.ServiceSpec{ClusterIP: "3000::1"}, + }, + &corev1.Service{ // empty, ignored + ObjectMeta: metav1.ObjectMeta{Namespace: "four", Name: "four"}, + Spec: corev1.ServiceSpec{ClusterIP: ""}, + }, + &corev1.Service{ // duplicate, dropped + ObjectMeta: metav1.ObjectMeta{Namespace: "five", Name: "five"}, + Spec: corev1.ServiceSpec{ClusterIP: "192.168.1.1"}, + }, + &corev1.Service{ // duplicate, dropped + ObjectMeta: metav1.ObjectMeta{Namespace: "five", Name: "five-v6"}, + Spec: corev1.ServiceSpec{ClusterIP: "2000::2"}, + }, + + &corev1.Service{ // headless + ObjectMeta: metav1.ObjectMeta{Namespace: "six", Name: "six"}, + Spec: corev1.ServiceSpec{ClusterIP: "None"}, + }, + ) + + ipregistry := &mockRangeRegistry{ + item: &api.RangeAllocation{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "1", + }, + Range: dst.Range, + Data: dst.Data, + }, + } + + secondaryIPRegistry := &mockRangeRegistry{ + item: &api.RangeAllocation{ + ObjectMeta: metav1.ObjectMeta{ + ResourceVersion: "1", + }, + Range: secondaryDST.Range, + Data: secondaryDST.Data, + }, + } + + r := NewRepair(0, fakeClient.CoreV1(), fakeClient.CoreV1(), cidr, ipregistry, secondaryCIDR, secondaryIPRegistry) + if err := r.RunOnce(); err != nil { + t.Fatal(err) + } + after, err := ipallocator.NewFromSnapshot(ipregistry.updated) + if err != nil { + t.Fatal(err) + } + + if !after.Has(net.ParseIP("192.168.1.1")) || !after.Has(net.ParseIP("192.168.1.100")) { + t.Errorf("unexpected ipallocator state: %#v", after) + } + if free := after.Free(); free != 252 { + t.Errorf("unexpected ipallocator state: %d free (number of free ips is not 252)", free) + } + secondaryAfter, err := ipallocator.NewFromSnapshot(secondaryIPRegistry.updated) + if err != nil { + t.Fatal(err) + } + if !secondaryAfter.Has(net.ParseIP("2000::1")) || !secondaryAfter.Has(net.ParseIP("2000::2")) { + t.Errorf("unexpected ipallocator state: %#v", secondaryAfter) + } + if free := secondaryAfter.Free(); free != 65532 { + t.Errorf("unexpected ipallocator state: %d free (number of free ips is not 65532)", free) + } + +} diff --git a/pkg/registry/core/service/storage/rest.go b/pkg/registry/core/service/storage/rest.go index 6743b316d4b..c45af066f15 100644 --- a/pkg/registry/core/service/storage/rest.go +++ b/pkg/registry/core/service/storage/rest.go @@ -46,16 +46,22 @@ import ( registry "k8s.io/kubernetes/pkg/registry/core/service" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" "k8s.io/kubernetes/pkg/registry/core/service/portallocator" + netutil "k8s.io/utils/net" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/kubernetes/pkg/features" ) // REST adapts a service registry into apiserver's RESTStorage model. type REST struct { - services ServiceStorage - endpoints EndpointsStorage - serviceIPs ipallocator.Interface - serviceNodePorts portallocator.Interface - proxyTransport http.RoundTripper - pods rest.Getter + services ServiceStorage + endpoints EndpointsStorage + serviceIPs ipallocator.Interface + secondaryServiceIPs ipallocator.Interface + defaultServiceIPFamily api.IPFamily + serviceNodePorts portallocator.Interface + proxyTransport http.RoundTripper + pods rest.Getter } // ServiceNodePort includes protocol and port number of a service NodePort. @@ -94,16 +100,29 @@ func NewREST( endpoints EndpointsStorage, pods rest.Getter, serviceIPs ipallocator.Interface, + secondaryServiceIPs ipallocator.Interface, serviceNodePorts portallocator.Interface, proxyTransport http.RoundTripper, ) (*REST, *registry.ProxyREST) { + // detect this cluster default Service IPFamily (ipfamily of --service-cluster-ip-range) + // we do it once here, to avoid having to do it over and over during ipfamily assignment + serviceIPFamily := api.IPv4Protocol + cidr := serviceIPs.CIDR() + if netutil.IsIPv6CIDR(&cidr) { + serviceIPFamily = api.IPv6Protocol + } + + klog.V(0).Infof("the default service ipfamily for this cluster is: %s", string(serviceIPFamily)) + rest := &REST{ - services: services, - endpoints: endpoints, - serviceIPs: serviceIPs, - serviceNodePorts: serviceNodePorts, - proxyTransport: proxyTransport, - pods: pods, + services: services, + endpoints: endpoints, + serviceIPs: serviceIPs, + secondaryServiceIPs: secondaryServiceIPs, + serviceNodePorts: serviceNodePorts, + defaultServiceIPFamily: serviceIPFamily, + proxyTransport: proxyTransport, + pods: pods, } return rest, ®istry.ProxyREST{Redirector: rest, ProxyTransport: proxyTransport} } @@ -160,6 +179,11 @@ func (rs *REST) Export(ctx context.Context, name string, opts metav1.ExportOptio func (rs *REST) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { service := obj.(*api.Service) + // set the service ip family, if it was not already set + if utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) && service.Spec.IPFamily == nil { + service.Spec.IPFamily = &rs.defaultServiceIPFamily + } + if err := rest.BeforeCreate(registry.Strategy, ctx, obj); err != nil { return nil, err } @@ -169,7 +193,8 @@ func (rs *REST) Create(ctx context.Context, obj runtime.Object, createValidation defer func() { if releaseServiceIP { if helper.IsServiceIPSet(service) { - rs.serviceIPs.Release(net.ParseIP(service.Spec.ClusterIP)) + allocator := rs.getAllocatorByClusterIP(service) + allocator.Release(net.ParseIP(service.Spec.ClusterIP)) } } }() @@ -177,7 +202,8 @@ func (rs *REST) Create(ctx context.Context, obj runtime.Object, createValidation var err error if !dryrun.IsDryRun(options.DryRun) { if service.Spec.Type != api.ServiceTypeExternalName { - if releaseServiceIP, err = initClusterIP(service, rs.serviceIPs); err != nil { + allocator := rs.getAllocatorBySpec(service) + if releaseServiceIP, err = initClusterIP(service, allocator); err != nil { return nil, err } } @@ -256,7 +282,8 @@ func (rs *REST) Delete(ctx context.Context, id string, deleteValidation rest.Val func (rs *REST) releaseAllocatedResources(svc *api.Service) { if helper.IsServiceIPSet(svc) { - rs.serviceIPs.Release(net.ParseIP(svc.Spec.ClusterIP)) + allocator := rs.getAllocatorByClusterIP(svc) + allocator.Release(net.ParseIP(svc.Spec.ClusterIP)) } for _, nodePort := range collectServiceNodePorts(svc) { @@ -365,6 +392,7 @@ func (rs *REST) Update(ctx context.Context, name string, objInfo rest.UpdatedObj } service := obj.(*api.Service) + if !rest.ValidNamespace(ctx, &service.ObjectMeta) { return nil, false, errors.NewConflict(api.Resource("services"), service.Namespace, fmt.Errorf("Service.Namespace does not match the provided context")) } @@ -379,7 +407,8 @@ func (rs *REST) Update(ctx context.Context, name string, objInfo rest.UpdatedObj defer func() { if releaseServiceIP { if helper.IsServiceIPSet(service) { - rs.serviceIPs.Release(net.ParseIP(service.Spec.ClusterIP)) + allocator := rs.getAllocatorByClusterIP(service) + allocator.Release(net.ParseIP(service.Spec.ClusterIP)) } } }() @@ -389,15 +418,19 @@ func (rs *REST) Update(ctx context.Context, name string, objInfo rest.UpdatedObj if !dryrun.IsDryRun(options.DryRun) { // Update service from ExternalName to non-ExternalName, should initialize ClusterIP. + // Since we don't support changing the ip family of a service we don't need to handle + // oldService.Spec.ServiceIPFamily != service.Spec.ServiceIPFamily if oldService.Spec.Type == api.ServiceTypeExternalName && service.Spec.Type != api.ServiceTypeExternalName { - if releaseServiceIP, err = initClusterIP(service, rs.serviceIPs); err != nil { + allocator := rs.getAllocatorBySpec(service) + if releaseServiceIP, err = initClusterIP(service, allocator); err != nil { return nil, false, err } } // Update service from non-ExternalName to ExternalName, should release ClusterIP if exists. if oldService.Spec.Type != api.ServiceTypeExternalName && service.Spec.Type == api.ServiceTypeExternalName { if helper.IsServiceIPSet(oldService) { - rs.serviceIPs.Release(net.ParseIP(oldService.Spec.ClusterIP)) + allocator := rs.getAllocatorByClusterIP(service) + allocator.Release(net.ParseIP(oldService.Spec.ClusterIP)) } } } @@ -521,6 +554,35 @@ func (r *REST) ConvertToTable(ctx context.Context, object runtime.Object, tableO return r.services.ConvertToTable(ctx, object, tableOptions) } +// When allocating we always use BySpec, when releasing we always use ByClusterIP +func (r *REST) getAllocatorByClusterIP(service *api.Service) ipallocator.Interface { + if !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) || r.secondaryServiceIPs == nil { + return r.serviceIPs + } + + secondaryAllocatorCIDR := r.secondaryServiceIPs.CIDR() + if netutil.IsIPv6String(service.Spec.ClusterIP) && netutil.IsIPv6CIDR(&secondaryAllocatorCIDR) { + return r.secondaryServiceIPs + } + + return r.serviceIPs +} + +func (r *REST) getAllocatorBySpec(service *api.Service) ipallocator.Interface { + if !utilfeature.DefaultFeatureGate.Enabled(features.IPv6DualStack) || + service.Spec.IPFamily == nil || + r.secondaryServiceIPs == nil { + return r.serviceIPs + } + + secondaryAllocatorCIDR := r.secondaryServiceIPs.CIDR() + if *(service.Spec.IPFamily) == api.IPv6Protocol && netutil.IsIPv6CIDR(&secondaryAllocatorCIDR) { + return r.secondaryServiceIPs + } + + return r.serviceIPs +} + func isValidAddress(ctx context.Context, addr *api.EndpointAddress, pods rest.Getter) error { if addr.TargetRef == nil { return fmt.Errorf("Address has no target ref, skipping: %v", addr) @@ -603,11 +665,11 @@ func allocateHealthCheckNodePort(service *api.Service, nodePortOp *portallocator } // The return bool value indicates if a cluster IP is allocated successfully. -func initClusterIP(service *api.Service, serviceIPs ipallocator.Interface) (bool, error) { +func initClusterIP(service *api.Service, allocator ipallocator.Interface) (bool, error) { switch { case service.Spec.ClusterIP == "": // Allocate next available. - ip, err := serviceIPs.AllocateNext() + ip, err := allocator.AllocateNext() if err != nil { // TODO: what error should be returned here? It's not a // field-level validation failure (the field is valid), and it's @@ -618,7 +680,7 @@ func initClusterIP(service *api.Service, serviceIPs ipallocator.Interface) (bool return true, nil case service.Spec.ClusterIP != api.ClusterIPNone && service.Spec.ClusterIP != "": // Try to respect the requested IP. - if err := serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil { + if err := allocator.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil { // TODO: when validation becomes versioned, this gets more complicated. el := field.ErrorList{field.Invalid(field.NewPath("spec", "clusterIP"), service.Spec.ClusterIP, err.Error())} return false, errors.NewInvalid(api.Kind("Service"), service.Name, el) diff --git a/pkg/registry/core/service/storage/rest_test.go b/pkg/registry/core/service/storage/rest_test.go index c92d1502244..3a2abfd05c4 100644 --- a/pkg/registry/core/service/storage/rest_test.go +++ b/pkg/registry/core/service/storage/rest_test.go @@ -17,6 +17,7 @@ limitations under the License. package storage import ( + "bytes" "context" "net" "reflect" @@ -41,12 +42,15 @@ import ( "k8s.io/kubernetes/pkg/api/service" api "k8s.io/kubernetes/pkg/apis/core" - "k8s.io/kubernetes/pkg/apis/core/helper" endpointstore "k8s.io/kubernetes/pkg/registry/core/endpoint/storage" podstore "k8s.io/kubernetes/pkg/registry/core/pod/storage" "k8s.io/kubernetes/pkg/registry/core/service/ipallocator" "k8s.io/kubernetes/pkg/registry/core/service/portallocator" "k8s.io/kubernetes/pkg/registry/registrytest" + + utilfeature "k8s.io/apiserver/pkg/util/feature" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/kubernetes/pkg/features" ) // TODO(wojtek-t): Cleanup this file. @@ -167,11 +171,11 @@ func generateRandomNodePort() int32 { return int32(rand.IntnRange(30001, 30999)) } -func NewTestREST(t *testing.T, endpoints *api.EndpointsList) (*REST, *serviceStorage, *etcd3testing.EtcdTestServer) { - return NewTestRESTWithPods(t, endpoints, nil) +func NewTestREST(t *testing.T, endpoints *api.EndpointsList, dualStack bool) (*REST, *serviceStorage, *etcd3testing.EtcdTestServer) { + return NewTestRESTWithPods(t, endpoints, nil, dualStack) } -func NewTestRESTWithPods(t *testing.T, endpoints *api.EndpointsList, pods *api.PodList) (*REST, *serviceStorage, *etcd3testing.EtcdTestServer) { +func NewTestRESTWithPods(t *testing.T, endpoints *api.EndpointsList, pods *api.PodList, dualStack bool) (*REST, *serviceStorage, *etcd3testing.EtcdTestServer) { etcdStorage, server := registrytest.NewEtcdStorage(t, "") serviceStorage := &serviceStorage{} @@ -216,6 +220,13 @@ func NewTestRESTWithPods(t *testing.T, endpoints *api.EndpointsList, pods *api.P if err != nil { t.Fatalf("cannot create CIDR Range %v", err) } + var rSecondary ipallocator.Interface + if dualStack { + rSecondary, err = ipallocator.NewCIDRRange(makeIPNet6(t)) + if err != nil { + t.Fatalf("cannot create CIDR Range(secondary) %v", err) + } + } portRange := utilnet.PortRange{Base: 30000, Size: 1000} portAllocator, err := portallocator.NewPortAllocator(portRange) @@ -223,7 +234,7 @@ func NewTestRESTWithPods(t *testing.T, endpoints *api.EndpointsList, pods *api.P t.Fatalf("cannot create port allocator %v", err) } - rest, _ := NewREST(serviceStorage, endpointStorage, podStorage.Pod, r, portAllocator, nil) + rest, _ := NewREST(serviceStorage, endpointStorage, podStorage.Pod, r, rSecondary, portAllocator, nil) return rest, serviceStorage, server } @@ -235,6 +246,27 @@ func makeIPNet(t *testing.T) *net.IPNet { } return net } +func makeIPNet6(t *testing.T) *net.IPNet { + _, net, err := net.ParseCIDR("2000::/108") + if err != nil { + t.Error(err) + } + return net +} + +func ipnetGet(t *testing.T, secondary bool) *net.IPNet { + if secondary { + return makeIPNet6(t) + } + return makeIPNet(t) +} + +func allocGet(r *REST, secondary bool) ipallocator.Interface { + if secondary { + return r.secondaryServiceIPs + } + return r.serviceIPs +} func releaseServiceNodePorts(t *testing.T, ctx context.Context, svcName string, rest *REST, registry ServiceStorage) { obj, err := registry.Get(ctx, svcName, &metav1.GetOptions{}) @@ -256,90 +288,214 @@ func releaseServiceNodePorts(t *testing.T, ctx context.Context, svcName string, } func TestServiceRegistryCreate(t *testing.T) { - storage, registry, server := NewTestREST(t, nil) - defer server.Terminate(t) + ipv4Service := api.IPv4Protocol + ipv6Service := api.IPv6Protocol - svc := &api.Service{ - ObjectMeta: metav1.ObjectMeta{Name: "foo"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"bar": "baz"}, - SessionAffinity: api.ServiceAffinityNone, - Type: api.ServiceTypeClusterIP, - Ports: []api.ServicePort{{ - Port: 6502, - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(6502), - }}, + testCases := []struct { + svc *api.Service + name string + enableDualStack bool + useSecondary bool + }{ + { + name: "Service IPFamily default cluster dualstack:off", + enableDualStack: false, + useSecondary: false, + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + }, + { + name: "Service IPFamily:v4 dualstack off", + enableDualStack: false, + useSecondary: false, + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv4Service, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + }, + { + name: "Service IPFamily:v4 dualstack on", + enableDualStack: true, + useSecondary: false, + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv4Service, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + }, + { + name: "Service IPFamily:v6 dualstack on", + enableDualStack: true, + useSecondary: true, + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv6Service, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, }, } - ctx := genericapirequest.NewDefaultContext() - created_svc, err := storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - created_service := created_svc.(*api.Service) - objMeta, err := meta.Accessor(created_service) - if err != nil { - t.Fatal(err) - } - if !metav1.HasObjectMetaSystemFieldValues(objMeta) { - t.Errorf("storage did not populate object meta field values") - } - if created_service.Name != "foo" { - t.Errorf("Expected foo, but got %v", created_service.Name) - } - if created_service.CreationTimestamp.IsZero() { - t.Errorf("Expected timestamp to be set, got: %v", created_service.CreationTimestamp) - } - if !makeIPNet(t).Contains(net.ParseIP(created_service.Spec.ClusterIP)) { - t.Errorf("Unexpected ClusterIP: %s", created_service.Spec.ClusterIP) - } - srv, err := registry.GetService(ctx, svc.Name, &metav1.GetOptions{}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if srv == nil { - t.Errorf("Failed to find service: %s", svc.Name) + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.enableDualStack)() + storage, registry, server := NewTestREST(t, nil, tc.enableDualStack) + defer server.Terminate(t) + + ctx := genericapirequest.NewDefaultContext() + created_svc, err := storage.Create(ctx, tc.svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + created_service := created_svc.(*api.Service) + objMeta, err := meta.Accessor(created_service) + if err != nil { + t.Fatal(err) + } + if !metav1.HasObjectMetaSystemFieldValues(objMeta) { + t.Errorf("storage did not populate object meta field values") + } + if created_service.Name != "foo" { + t.Errorf("Expected foo, but got %v", created_service.Name) + } + if created_service.CreationTimestamp.IsZero() { + t.Errorf("Expected timestamp to be set, got: %v", created_service.CreationTimestamp) + } + allocNet := ipnetGet(t, tc.useSecondary) + + if !allocNet.Contains(net.ParseIP(created_service.Spec.ClusterIP)) { + t.Errorf("Unexpected ClusterIP: %s", created_service.Spec.ClusterIP) + } + srv, err := registry.GetService(ctx, tc.svc.Name, &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if srv == nil { + t.Errorf("Failed to find service: %s", tc.svc.Name) + } + }) } } func TestServiceRegistryCreateDryRun(t *testing.T) { - storage, registry, server := NewTestREST(t, nil) - defer server.Terminate(t) - - // Test dry run create request with cluster ip - svc := &api.Service{ - ObjectMeta: metav1.ObjectMeta{Name: "foo"}, - Spec: api.ServiceSpec{ - Selector: map[string]string{"bar": "baz"}, - SessionAffinity: api.ServiceAffinityNone, - Type: api.ServiceTypeClusterIP, - ClusterIP: "1.2.3.4", - Ports: []api.ServicePort{{ - Port: 6502, - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(6502), - }}, + ipv6Service := api.IPv6Protocol + testCases := []struct { + name string + svc *api.Service + enableDualStack bool + useSecondary bool + }{ + { + name: "v4 service", + enableDualStack: false, + useSecondary: false, + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + ClusterIP: "1.2.3.4", + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + }, + { + name: "v6 service", + enableDualStack: true, + useSecondary: true, + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv6Service, + ClusterIP: "2000:0:0:0:0:0:0:1", + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, }, } - ctx := genericapirequest.NewDefaultContext() - _, err := storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}}) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if storage.serviceIPs.Has(net.ParseIP("1.2.3.4")) { - t.Errorf("unexpected side effect: ip allocated") - } - srv, err := registry.GetService(ctx, svc.Name, &metav1.GetOptions{}) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - if srv != nil { - t.Errorf("unexpected service found: %v", srv) + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.enableDualStack)() + storage, registry, server := NewTestREST(t, nil, tc.enableDualStack) + defer server.Terminate(t) + + ctx := genericapirequest.NewDefaultContext() + _, err := storage.Create(ctx, tc.svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}}) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + alloc := allocGet(storage, tc.useSecondary) + + if alloc.Has(net.ParseIP(tc.svc.Spec.ClusterIP)) { + t.Errorf("unexpected side effect: ip allocated") + } + srv, err := registry.GetService(ctx, tc.svc.Name, &metav1.GetOptions{}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if srv != nil { + t.Errorf("unexpected service found: %v", srv) + } + }) } +} + +func TestDryRunNodePort(t *testing.T) { + storage, registry, server := NewTestREST(t, nil, false) + defer server.Terminate(t) // Test dry run create request with a node port - svc = &api.Service{ + svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, Spec: api.ServiceSpec{ Selector: map[string]string{"bar": "baz"}, @@ -353,14 +509,16 @@ func TestServiceRegistryCreateDryRun(t *testing.T) { }}, }, } - _, err = storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}}) + ctx := genericapirequest.NewDefaultContext() + + _, err := storage.Create(ctx, svc, rest.ValidateAllObjectFunc, &metav1.CreateOptions{DryRun: []string{metav1.DryRunAll}}) if err != nil { t.Fatalf("Unexpected error: %v", err) } if storage.serviceNodePorts.Has(30010) { t.Errorf("unexpected side effect: NodePort allocated") } - srv, err = registry.GetService(ctx, svc.Name, &metav1.GetOptions{}) + srv, err := registry.GetService(ctx, svc.Name, &metav1.GetOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } @@ -452,7 +610,8 @@ func TestServiceRegistryCreateDryRun(t *testing.T) { } func TestServiceRegistryCreateMultiNodePortsService(t *testing.T) { - storage, registry, server := NewTestREST(t, nil) + + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) testCases := []struct { @@ -582,7 +741,7 @@ func TestServiceRegistryCreateMultiNodePortsService(t *testing.T) { } func TestServiceStorageValidatesCreate(t *testing.T) { - storage, _, server := NewTestREST(t, nil) + storage, _, server := NewTestREST(t, nil, false) defer server.Terminate(t) failureCases := map[string]api.Service{ "empty ID": { @@ -636,7 +795,7 @@ func TestServiceStorageValidatesCreate(t *testing.T) { func TestServiceRegistryUpdate(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) obj, err := registry.Create(ctx, &api.Service{ @@ -688,8 +847,9 @@ func TestServiceRegistryUpdate(t *testing.T) { } func TestServiceRegistryUpdateDryRun(t *testing.T) { + ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) obj, err := registry.Create(ctx, &api.Service{ @@ -854,7 +1014,7 @@ func TestServiceRegistryUpdateDryRun(t *testing.T) { func TestServiceStorageValidatesUpdate(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) registry.Create(ctx, &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, @@ -907,7 +1067,7 @@ func TestServiceStorageValidatesUpdate(t *testing.T) { func TestServiceRegistryExternalService(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, @@ -946,7 +1106,7 @@ func TestServiceRegistryExternalService(t *testing.T) { func TestServiceRegistryDelete(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, @@ -969,7 +1129,7 @@ func TestServiceRegistryDelete(t *testing.T) { func TestServiceRegistryDeleteDryRun(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) // Test dry run delete request with cluster ip @@ -1035,7 +1195,7 @@ func TestServiceRegistryDeleteDryRun(t *testing.T) { func TestServiceRegistryDeleteExternal(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, @@ -1058,7 +1218,7 @@ func TestServiceRegistryDeleteExternal(t *testing.T) { func TestServiceRegistryUpdateExternalService(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) // Create non-external load balancer. @@ -1097,7 +1257,7 @@ func TestServiceRegistryUpdateExternalService(t *testing.T) { func TestServiceRegistryUpdateMultiPortExternalService(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) // Create external load balancer. @@ -1135,7 +1295,7 @@ func TestServiceRegistryUpdateMultiPortExternalService(t *testing.T) { func TestServiceRegistryGet(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) registry.Create(ctx, &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo"}, @@ -1211,7 +1371,7 @@ func TestServiceRegistryResourceLocation(t *testing.T) { }, }, } - storage, registry, server := NewTestRESTWithPods(t, endpoints, pods) + storage, registry, server := NewTestRESTWithPods(t, endpoints, pods, false) defer server.Terminate(t) for _, name := range []string{"foo", "bad"} { registry.Create(ctx, &api.Service{ @@ -1311,7 +1471,7 @@ func TestServiceRegistryResourceLocation(t *testing.T) { func TestServiceRegistryList(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) registry.Create(ctx, &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: metav1.NamespaceDefault}, @@ -1343,7 +1503,7 @@ func TestServiceRegistryList(t *testing.T) { } func TestServiceRegistryIPAllocation(t *testing.T) { - storage, _, server := NewTestREST(t, nil) + storage, _, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc1 := &api.Service{ @@ -1426,7 +1586,7 @@ func TestServiceRegistryIPAllocation(t *testing.T) { } func TestServiceRegistryIPReallocation(t *testing.T) { - storage, _, server := NewTestREST(t, nil) + storage, _, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc1 := &api.Service{ @@ -1482,7 +1642,7 @@ func TestServiceRegistryIPReallocation(t *testing.T) { } func TestServiceRegistryIPUpdate(t *testing.T) { - storage, _, server := NewTestREST(t, nil) + storage, _, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ @@ -1537,7 +1697,7 @@ func TestServiceRegistryIPUpdate(t *testing.T) { } func TestServiceRegistryIPLoadBalancer(t *testing.T) { - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ @@ -1577,7 +1737,7 @@ func TestServiceRegistryIPLoadBalancer(t *testing.T) { } func TestUpdateServiceWithConflictingNamespace(t *testing.T) { - storage, _, server := NewTestREST(t, nil) + storage, _, server := NewTestREST(t, nil, false) defer server.Terminate(t) service := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "not-default"}, @@ -1599,7 +1759,7 @@ func TestUpdateServiceWithConflictingNamespace(t *testing.T) { // and type is LoadBalancer. func TestServiceRegistryExternalTrafficHealthCheckNodePortAllocation(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "external-lb-esipp"}, @@ -1639,7 +1799,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortAllocation(t *testing. func TestServiceRegistryExternalTrafficHealthCheckNodePortUserAllocation(t *testing.T) { randomNodePort := generateRandomNodePort() ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "external-lb-esipp"}, @@ -1682,7 +1842,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortUserAllocation(t *test // Validate that the service creation fails when the requested port number is -1. func TestServiceRegistryExternalTrafficHealthCheckNodePortNegative(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, _, server := NewTestREST(t, nil) + storage, _, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "external-lb-esipp"}, @@ -1709,7 +1869,7 @@ func TestServiceRegistryExternalTrafficHealthCheckNodePortNegative(t *testing.T) // Validate that the health check nodePort is not allocated when ExternalTrafficPolicy is set to Global. func TestServiceRegistryExternalTrafficGlobal(t *testing.T) { ctx := genericapirequest.NewDefaultContext() - storage, registry, server := NewTestREST(t, nil) + storage, registry, server := NewTestREST(t, nil, false) defer server.Terminate(t) svc := &api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "external-lb-esipp"}, @@ -1745,13 +1905,17 @@ func TestServiceRegistryExternalTrafficGlobal(t *testing.T) { } func TestInitClusterIP(t *testing.T) { - storage, _, server := NewTestREST(t, nil) - defer server.Terminate(t) - + ipv4Service := api.IPv4Protocol + ipv6Service := api.IPv6Protocol testCases := []struct { - name string - svc *api.Service - expectClusterIP bool + name string + svc *api.Service + + expectClusterIP bool + enableDualStack bool + allocateSpecificIP bool + useSecondaryAlloc bool + expectedAllocatedIP string }{ { name: "Allocate new ClusterIP", @@ -1769,6 +1933,27 @@ func TestInitClusterIP(t *testing.T) { }, }, expectClusterIP: true, + enableDualStack: false, + }, + { + name: "Allocate new ClusterIP-v6", + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv6Service, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + expectClusterIP: true, + useSecondaryAlloc: true, + enableDualStack: true, }, { name: "Allocate specified ClusterIP", @@ -1778,6 +1963,7 @@ func TestInitClusterIP(t *testing.T) { Selector: map[string]string{"bar": "baz"}, SessionAffinity: api.ServiceAffinityNone, Type: api.ServiceTypeClusterIP, + IPFamily: &ipv4Service, ClusterIP: "1.2.3.4", Ports: []api.ServicePort{{ Port: 6502, @@ -1786,7 +1972,33 @@ func TestInitClusterIP(t *testing.T) { }}, }, }, - expectClusterIP: true, + expectClusterIP: true, + allocateSpecificIP: true, + expectedAllocatedIP: "1.2.3.4", + enableDualStack: true, + }, + { + name: "Allocate specified ClusterIP-v6", + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv6Service, + ClusterIP: "2000:0:0:0:0:0:0:1", + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + expectClusterIP: true, + allocateSpecificIP: true, + expectedAllocatedIP: "2000:0:0:0:0:0:0:1", + useSecondaryAlloc: true, + enableDualStack: true, }, { name: "Shouldn't allocate ClusterIP", @@ -1809,35 +2021,41 @@ func TestInitClusterIP(t *testing.T) { } for _, test := range testCases { - hasAllocatedIP, err := initClusterIP(test.svc, storage.serviceIPs) - if err != nil { - t.Errorf("%q: unexpected error: %v", test.name, err) - } + t.Run(test.name, func(t *testing.T) { - if hasAllocatedIP != test.expectClusterIP { - t.Errorf("%q: expected %v, but got %v", test.name, test.expectClusterIP, hasAllocatedIP) - } + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, test.enableDualStack)() - if test.expectClusterIP { - if !storage.serviceIPs.Has(net.ParseIP(test.svc.Spec.ClusterIP)) { - t.Errorf("%q: unexpected ClusterIP %q, out of range", test.name, test.svc.Spec.ClusterIP) + storage, _, server := NewTestREST(t, nil, test.enableDualStack) + defer server.Terminate(t) + + whichAlloc := allocGet(storage, test.useSecondaryAlloc) + hasAllocatedIP, err := initClusterIP(test.svc, whichAlloc) + if err != nil { + t.Errorf("unexpected error: %v", err) } - } - if test.name == "Allocate specified ClusterIP" && test.svc.Spec.ClusterIP != "1.2.3.4" { - t.Errorf("%q: expected ClusterIP %q, but got %q", test.name, "1.2.3.4", test.svc.Spec.ClusterIP) - } - - if hasAllocatedIP { - if helper.IsServiceIPSet(test.svc) { - storage.serviceIPs.Release(net.ParseIP(test.svc.Spec.ClusterIP)) + if hasAllocatedIP != test.expectClusterIP { + t.Errorf("expected %v, but got %v", test.expectClusterIP, hasAllocatedIP) } - } + + if test.expectClusterIP { + alloc := allocGet(storage, test.useSecondaryAlloc) + if !alloc.Has(net.ParseIP(test.svc.Spec.ClusterIP)) { + t.Errorf("unexpected ClusterIP %q, out of range", test.svc.Spec.ClusterIP) + } + } + + if test.allocateSpecificIP && test.expectedAllocatedIP != test.svc.Spec.ClusterIP { + t.Errorf(" expected ClusterIP %q, but got %q", test.expectedAllocatedIP, test.svc.Spec.ClusterIP) + } + + }) } + } func TestInitNodePorts(t *testing.T) { - storage, _, server := NewTestREST(t, nil) + storage, _, server := NewTestREST(t, nil, false) defer server.Terminate(t) nodePortOp := portallocator.StartOperation(storage.serviceNodePorts, false) defer nodePortOp.Finish() @@ -2019,7 +2237,7 @@ func TestInitNodePorts(t *testing.T) { } func TestUpdateNodePorts(t *testing.T) { - storage, _, server := NewTestREST(t, nil) + storage, _, server := NewTestREST(t, nil, false) defer server.Terminate(t) nodePortOp := portallocator.StartOperation(storage.serviceNodePorts, false) defer nodePortOp.Finish() @@ -2287,3 +2505,142 @@ func TestUpdateNodePorts(t *testing.T) { } } } + +func TestAllocGetters(t *testing.T) { + ipv4Service := api.IPv4Protocol + ipv6Service := api.IPv6Protocol + + testCases := []struct { + name string + + enableDualStack bool + specExpctPrimary bool + clusterIPExpectPrimary bool + + svc *api.Service + }{ + { + name: "spec:v4 ip:v4 dualstack:off", + + specExpctPrimary: true, + clusterIPExpectPrimary: true, + enableDualStack: false, + + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv4Service, + ClusterIP: "10.0.0.1", + }, + }, + }, + { + name: "spec:v4 ip:v4 dualstack:on", + + specExpctPrimary: true, + clusterIPExpectPrimary: true, + enableDualStack: true, + + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv4Service, + ClusterIP: "10.0.0.1", + }, + }, + }, + + { + name: "spec:v4 ip:v6 dualstack:on", + + specExpctPrimary: true, + clusterIPExpectPrimary: false, + enableDualStack: true, + + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv4Service, + ClusterIP: "2000::1", + }, + }, + }, + + { + name: "spec:v6 ip:v6 dualstack:on", + + specExpctPrimary: false, + clusterIPExpectPrimary: false, + enableDualStack: true, + + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv6Service, + ClusterIP: "2000::1", + }, + }, + }, + + { + name: "spec:v6 ip:v4 dualstack:on", + + specExpctPrimary: false, + clusterIPExpectPrimary: true, + enableDualStack: true, + + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", ResourceVersion: "1"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + Type: api.ServiceTypeClusterIP, + IPFamily: &ipv6Service, + ClusterIP: "10.0.0.10", + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IPv6DualStack, tc.enableDualStack)() + storage, _, server := NewTestREST(t, nil, tc.enableDualStack) + defer server.Terminate(t) + + if tc.enableDualStack && storage.secondaryServiceIPs == nil { + t.Errorf("storage must allocate secondary ServiceIPs allocator for dual stack") + return + } + + alloc := storage.getAllocatorByClusterIP(tc.svc) + if tc.clusterIPExpectPrimary && !bytes.Equal(alloc.CIDR().IP, storage.serviceIPs.CIDR().IP) { + t.Errorf("expected primary allocator, but primary allocator was not selected") + return + } + + if tc.enableDualStack && !tc.clusterIPExpectPrimary && !bytes.Equal(alloc.CIDR().IP, storage.secondaryServiceIPs.CIDR().IP) { + t.Errorf("expected secondary allocator, but secondary allocator was not selected") + } + + alloc = storage.getAllocatorBySpec(tc.svc) + if tc.specExpctPrimary && !bytes.Equal(alloc.CIDR().IP, storage.serviceIPs.CIDR().IP) { + t.Errorf("expected primary allocator, but primary allocator was not selected") + return + } + + if tc.enableDualStack && !tc.specExpctPrimary && !bytes.Equal(alloc.CIDR().IP, storage.secondaryServiceIPs.CIDR().IP) { + t.Errorf("expected secondary allocator, but secondary allocator was not selected") + } + + }) + } + +} diff --git a/test/e2e_node/services/apiserver.go b/test/e2e_node/services/apiserver.go index a86fe3e6daf..636b3d71f3e 100644 --- a/test/e2e_node/services/apiserver.go +++ b/test/e2e_node/services/apiserver.go @@ -53,7 +53,7 @@ func (a *APIServer) Start() error { if err != nil { return err } - o.ServiceClusterIPRange = *ipnet + o.ServiceClusterIPRanges = ipnet.String() o.AllowPrivileged = true o.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount", "TaintNodesByCondition"} errCh := make(chan error) diff --git a/test/integration/etcd/server.go b/test/integration/etcd/server.go index 2d8441b84c7..1ab178ae0c7 100644 --- a/test/integration/etcd/server.go +++ b/test/integration/etcd/server.go @@ -76,7 +76,7 @@ func StartRealMasterOrDie(t *testing.T, configFuncs ...func(*options.ServerRunOp kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir kubeAPIServerOptions.Etcd.StorageConfig.Transport.ServerList = []string{framework.GetEtcdURL()} kubeAPIServerOptions.Etcd.DefaultStorageMediaType = runtime.ContentTypeJSON // force json we can easily interpret the result in etcd - kubeAPIServerOptions.ServiceClusterIPRange = *defaultServiceClusterIPRange + kubeAPIServerOptions.ServiceClusterIPRanges = defaultServiceClusterIPRange.String() kubeAPIServerOptions.Authorization.Modes = []string{"RBAC"} kubeAPIServerOptions.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount"} kubeAPIServerOptions.APIEnablement.RuntimeConfig["api/all"] = "true" diff --git a/test/integration/examples/apiserver_test.go b/test/integration/examples/apiserver_test.go index f3ce8862ed1..b93387f5616 100644 --- a/test/integration/examples/apiserver_test.go +++ b/test/integration/examples/apiserver_test.go @@ -101,7 +101,7 @@ func TestAggregatedAPIServer(t *testing.T) { kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir kubeAPIServerOptions.InsecureServing.BindPort = 0 kubeAPIServerOptions.Etcd.StorageConfig.Transport.ServerList = []string{framework.GetEtcdURL()} - kubeAPIServerOptions.ServiceClusterIPRange = *defaultServiceClusterIPRange + kubeAPIServerOptions.ServiceClusterIPRanges = defaultServiceClusterIPRange.String() kubeAPIServerOptions.Authentication.RequestHeader.UsernameHeaders = []string{"X-Remote-User"} kubeAPIServerOptions.Authentication.RequestHeader.GroupHeaders = []string{"X-Remote-Group"} kubeAPIServerOptions.Authentication.RequestHeader.ExtraHeaderPrefixes = []string{"X-Remote-Extra-"} diff --git a/test/integration/framework/test_server.go b/test/integration/framework/test_server.go index 32ba52f4093..a92e1d2f49c 100644 --- a/test/integration/framework/test_server.go +++ b/test/integration/framework/test_server.go @@ -92,7 +92,7 @@ func StartTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup kubeAPIServerOptions.InsecureServing.BindPort = 0 kubeAPIServerOptions.Etcd.StorageConfig.Prefix = path.Join("/", uuid.New(), "registry") kubeAPIServerOptions.Etcd.StorageConfig.Transport.ServerList = []string{GetEtcdURL()} - kubeAPIServerOptions.ServiceClusterIPRange = *defaultServiceClusterIPRange + kubeAPIServerOptions.ServiceClusterIPRanges = defaultServiceClusterIPRange.String() kubeAPIServerOptions.Authentication.RequestHeader.UsernameHeaders = []string{"X-Remote-User"} kubeAPIServerOptions.Authentication.RequestHeader.GroupHeaders = []string{"X-Remote-Group"} kubeAPIServerOptions.Authentication.RequestHeader.ExtraHeaderPrefixes = []string{"X-Remote-Extra-"} From 313a5c57347026055fdcfefcdd626a7ab3357f84 Mon Sep 17 00:00:00 2001 From: "Khaled Henidak(Kal)" Date: Mon, 19 Aug 2019 20:53:18 +0000 Subject: [PATCH 3/4] phase 2: ipam filter secondary service cidr --- api/api-rules/violation_exceptions.list | 1 + cmd/kube-controller-manager/app/core.go | 26 ++++++++++ .../app/options/nodeipamcontroller.go | 21 +++++++-- pkg/controller/nodeipam/config/types.go | 2 + .../nodeipam/ipam/cidr_allocator.go | 4 +- .../nodeipam/ipam/range_allocator.go | 9 +++- .../nodeipam/ipam/range_allocator_test.go | 47 ++++++++++++------- .../nodeipam/node_ipam_controller.go | 25 +++++----- .../nodeipam/node_ipam_controller_test.go | 44 +++++++++-------- .../config/v1alpha1/types.go | 2 + test/integration/ipamperf/ipam_test.go | 2 +- 11 files changed, 128 insertions(+), 55 deletions(-) diff --git a/api/api-rules/violation_exceptions.list b/api/api-rules/violation_exceptions.list index 24733bab0b6..c6b9c863a36 100644 --- a/api/api-rules/violation_exceptions.list +++ b/api/api-rules/violation_exceptions.list @@ -636,6 +636,7 @@ API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,K API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NamespaceControllerConfiguration,ConcurrentNamespaceSyncs API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NamespaceControllerConfiguration,NamespaceSyncPeriod API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NodeIPAMControllerConfiguration,NodeCIDRMaskSize +API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NodeIPAMControllerConfiguration,SecondaryServiceCIDR API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NodeIPAMControllerConfiguration,ServiceCIDR API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NodeLifecycleControllerConfiguration,EnableTaintManager API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NodeLifecycleControllerConfiguration,LargeClusterSizeThreshold diff --git a/cmd/kube-controller-manager/app/core.go b/cmd/kube-controller-manager/app/core.go index d80c6e5a111..2a5d7ec64c5 100644 --- a/cmd/kube-controller-manager/app/core.go +++ b/cmd/kube-controller-manager/app/core.go @@ -83,6 +83,7 @@ func startServiceController(ctx ControllerContext) (http.Handler, bool, error) { } func startNodeIpamController(ctx ControllerContext) (http.Handler, bool, error) { var serviceCIDR *net.IPNet + var secondaryServiceCIDR *net.IPNet // should we start nodeIPAM if !ctx.ComponentConfig.KubeCloudShared.AllocateNodeCIDRs { @@ -118,12 +119,37 @@ func startNodeIpamController(ctx ControllerContext) (http.Handler, bool, error) } } + if len(strings.TrimSpace(ctx.ComponentConfig.NodeIPAMController.SecondaryServiceCIDR)) != 0 { + _, secondaryServiceCIDR, err = net.ParseCIDR(ctx.ComponentConfig.NodeIPAMController.SecondaryServiceCIDR) + if err != nil { + klog.Warningf("Unsuccessful parsing of service CIDR %v: %v", ctx.ComponentConfig.NodeIPAMController.SecondaryServiceCIDR, err) + } + } + + // the following checks are triggered if both serviceCIDR and secondaryServiceCIDR are provided + if serviceCIDR != nil && secondaryServiceCIDR != nil { + // should have dual stack flag enabled + if !utilfeature.DefaultFeatureGate.Enabled(kubefeatures.IPv6DualStack) { + return nil, false, fmt.Errorf("secondary service cidr is provided and IPv6DualStack feature is not enabled") + } + + // should be dual stack (from different IPFamilies) + dualstackServiceCIDR, err := netutils.IsDualStackCIDRs([]*net.IPNet{serviceCIDR, secondaryServiceCIDR}) + if err != nil { + return nil, false, fmt.Errorf("failed to perform dualstack check on serviceCIDR and secondaryServiceCIDR error:%v", err) + } + if !dualstackServiceCIDR { + return nil, false, fmt.Errorf("serviceCIDR and secondaryServiceCIDR are not dualstack (from different IPfamiles)") + } + } + nodeIpamController, err := nodeipamcontroller.NewNodeIpamController( ctx.InformerFactory.Core().V1().Nodes(), ctx.Cloud, ctx.ClientBuilder.ClientOrDie("node-controller"), clusterCIDRs, serviceCIDR, + secondaryServiceCIDR, int(ctx.ComponentConfig.NodeIPAMController.NodeCIDRMaskSize), ipam.CIDRAllocatorType(ctx.ComponentConfig.KubeCloudShared.CIDRAllocatorType), ) diff --git a/cmd/kube-controller-manager/app/options/nodeipamcontroller.go b/cmd/kube-controller-manager/app/options/nodeipamcontroller.go index f530b203451..158ce08be79 100644 --- a/cmd/kube-controller-manager/app/options/nodeipamcontroller.go +++ b/cmd/kube-controller-manager/app/options/nodeipamcontroller.go @@ -17,6 +17,9 @@ limitations under the License. package options import ( + "fmt" + "strings" + "github.com/spf13/pflag" nodeipamconfig "k8s.io/kubernetes/pkg/controller/nodeipam/config" @@ -32,7 +35,6 @@ func (o *NodeIPAMControllerOptions) AddFlags(fs *pflag.FlagSet) { if o == nil { return } - fs.StringVar(&o.ServiceCIDR, "service-cluster-ip-range", o.ServiceCIDR, "CIDR Range for Services in cluster. Requires --allocate-node-cidrs to be true") fs.Int32Var(&o.NodeCIDRMaskSize, "node-cidr-mask-size", o.NodeCIDRMaskSize, "Mask size for node cidr in cluster.") } @@ -43,7 +45,15 @@ func (o *NodeIPAMControllerOptions) ApplyTo(cfg *nodeipamconfig.NodeIPAMControll return nil } - cfg.ServiceCIDR = o.ServiceCIDR + // split the cidrs list and assign primary and secondary + serviceCIDRList := strings.Split(o.ServiceCIDR, ",") + if len(serviceCIDRList) > 0 { + cfg.ServiceCIDR = serviceCIDRList[0] + } + if len(serviceCIDRList) > 1 { + cfg.SecondaryServiceCIDR = serviceCIDRList[1] + } + cfg.NodeCIDRMaskSize = o.NodeCIDRMaskSize return nil @@ -54,7 +64,12 @@ func (o *NodeIPAMControllerOptions) Validate() []error { if o == nil { return nil } + errs := make([]error, 0) + + serviceCIDRList := strings.Split(o.ServiceCIDR, ",") + if len(serviceCIDRList) > 2 { + errs = append(errs, fmt.Errorf("--service-cluster-ip-range can not contain more than two entries")) + } - errs := []error{} return errs } diff --git a/pkg/controller/nodeipam/config/types.go b/pkg/controller/nodeipam/config/types.go index 2b6cb01cd60..66094406385 100644 --- a/pkg/controller/nodeipam/config/types.go +++ b/pkg/controller/nodeipam/config/types.go @@ -20,6 +20,8 @@ package config type NodeIPAMControllerConfiguration struct { // serviceCIDR is CIDR Range for Services in cluster. ServiceCIDR string + // secondaryServiceCIDR is CIDR Range for Services in cluster. This is used in dual stack clusters. SecondaryServiceCIDR must be of different IP family than ServiceCIDR + SecondaryServiceCIDR string // NodeCIDRMaskSize is the mask size for node cidr in cluster. NodeCIDRMaskSize int32 } diff --git a/pkg/controller/nodeipam/ipam/cidr_allocator.go b/pkg/controller/nodeipam/ipam/cidr_allocator.go index 96079a1688f..080d71b9cd5 100644 --- a/pkg/controller/nodeipam/ipam/cidr_allocator.go +++ b/pkg/controller/nodeipam/ipam/cidr_allocator.go @@ -89,7 +89,7 @@ type CIDRAllocator interface { } // New creates a new CIDR range allocator. -func New(kubeClient clientset.Interface, cloud cloudprovider.Interface, nodeInformer informers.NodeInformer, allocatorType CIDRAllocatorType, clusterCIDRs []*net.IPNet, serviceCIDR *net.IPNet, nodeCIDRMaskSize int) (CIDRAllocator, error) { +func New(kubeClient clientset.Interface, cloud cloudprovider.Interface, nodeInformer informers.NodeInformer, allocatorType CIDRAllocatorType, clusterCIDRs []*net.IPNet, serviceCIDR *net.IPNet, secondaryServiceCIDR *net.IPNet, nodeCIDRMaskSize int) (CIDRAllocator, error) { nodeList, err := listNodes(kubeClient) if err != nil { return nil, err @@ -97,7 +97,7 @@ func New(kubeClient clientset.Interface, cloud cloudprovider.Interface, nodeInfo switch allocatorType { case RangeAllocatorType: - return NewCIDRRangeAllocator(kubeClient, nodeInformer, clusterCIDRs, serviceCIDR, nodeCIDRMaskSize, nodeList) + return NewCIDRRangeAllocator(kubeClient, nodeInformer, clusterCIDRs, serviceCIDR, secondaryServiceCIDR, nodeCIDRMaskSize, nodeList) case CloudAllocatorType: return NewCloudCIDRAllocator(kubeClient, cloud, nodeInformer) default: diff --git a/pkg/controller/nodeipam/ipam/range_allocator.go b/pkg/controller/nodeipam/ipam/range_allocator.go index 4763450a866..0032e36a689 100644 --- a/pkg/controller/nodeipam/ipam/range_allocator.go +++ b/pkg/controller/nodeipam/ipam/range_allocator.go @@ -71,7 +71,7 @@ type rangeAllocator struct { // Caller must always pass in a list of existing nodes so the new allocator. // Caller must ensure that ClusterCIDRs are semantically correct e.g (1 for non DualStack, 2 for DualStack etc..) // can initialize its CIDR map. NodeList is only nil in testing. -func NewCIDRRangeAllocator(client clientset.Interface, nodeInformer informers.NodeInformer, clusterCIDRs []*net.IPNet, serviceCIDR *net.IPNet, subNetMaskSize int, nodeList *v1.NodeList) (CIDRAllocator, error) { +func NewCIDRRangeAllocator(client clientset.Interface, nodeInformer informers.NodeInformer, clusterCIDRs []*net.IPNet, serviceCIDR *net.IPNet, secondaryServiceCIDR *net.IPNet, subNetMaskSize int, nodeList *v1.NodeList) (CIDRAllocator, error) { if client == nil { klog.Fatalf("kubeClient is nil when starting NodeController") } @@ -110,6 +110,12 @@ func NewCIDRRangeAllocator(client clientset.Interface, nodeInformer informers.No klog.V(0).Info("No Service CIDR provided. Skipping filtering out service addresses.") } + if secondaryServiceCIDR != nil { + ra.filterOutServiceRange(secondaryServiceCIDR) + } else { + klog.V(0).Info("No Secondary Service CIDR provided. Skipping filtering out secondary service addresses.") + } + if nodeList != nil { for _, node := range nodeList.Items { if len(node.Spec.PodCIDRs) == 0 { @@ -295,6 +301,7 @@ func (r *rangeAllocator) filterOutServiceRange(serviceCIDR *net.IPNet) { // serviceCIDR) or vice versa (which means that serviceCIDR contains // clusterCIDR). for idx, cidr := range r.clusterCIDRs { + // if they don't overlap then ignore the filtering if !cidr.Contains(serviceCIDR.IP.Mask(cidr.Mask)) && !serviceCIDR.Contains(cidr.IP.Mask(serviceCIDR.Mask)) { continue } diff --git a/pkg/controller/nodeipam/ipam/range_allocator_test.go b/pkg/controller/nodeipam/ipam/range_allocator_test.go index 8bcf9de6f7d..8b5d1c1a19c 100644 --- a/pkg/controller/nodeipam/ipam/range_allocator_test.go +++ b/pkg/controller/nodeipam/ipam/range_allocator_test.go @@ -60,11 +60,12 @@ func getFakeNodeInformer(fakeNodeHandler *testutil.FakeNodeHandler) coreinformer } type testCase struct { - description string - fakeNodeHandler *testutil.FakeNodeHandler - clusterCIDRs []*net.IPNet - serviceCIDR *net.IPNet - subNetMaskSize int + description string + fakeNodeHandler *testutil.FakeNodeHandler + clusterCIDRs []*net.IPNet + serviceCIDR *net.IPNet + secondaryServiceCIDR *net.IPNet + subNetMaskSize int // key is index of the cidr allocated expectedAllocatedCIDR map[int]string allocatedCIDRs map[int][]string @@ -89,8 +90,9 @@ func TestAllocateOrOccupyCIDRSuccess(t *testing.T) { _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/24") return []*net.IPNet{clusterCIDR} }(), - serviceCIDR: nil, - subNetMaskSize: 30, + serviceCIDR: nil, + secondaryServiceCIDR: nil, + subNetMaskSize: 30, expectedAllocatedCIDR: map[int]string{ 0: "127.123.234.0/30", }, @@ -115,7 +117,8 @@ func TestAllocateOrOccupyCIDRSuccess(t *testing.T) { _, serviceCIDR, _ := net.ParseCIDR("127.123.234.0/26") return serviceCIDR }(), - subNetMaskSize: 30, + secondaryServiceCIDR: nil, + subNetMaskSize: 30, // it should return first /30 CIDR after service range expectedAllocatedCIDR: map[int]string{ 0: "127.123.234.64/30", @@ -141,7 +144,8 @@ func TestAllocateOrOccupyCIDRSuccess(t *testing.T) { _, serviceCIDR, _ := net.ParseCIDR("127.123.234.0/26") return serviceCIDR }(), - subNetMaskSize: 30, + secondaryServiceCIDR: nil, + subNetMaskSize: 30, allocatedCIDRs: map[int][]string{ 0: {"127.123.234.64/30", "127.123.234.68/30", "127.123.234.72/30", "127.123.234.80/30"}, }, @@ -170,6 +174,7 @@ func TestAllocateOrOccupyCIDRSuccess(t *testing.T) { _, serviceCIDR, _ := net.ParseCIDR("127.123.234.0/26") return serviceCIDR }(), + secondaryServiceCIDR: nil, }, { description: "Dualstack CIDRs v6,v4", @@ -192,6 +197,7 @@ func TestAllocateOrOccupyCIDRSuccess(t *testing.T) { _, serviceCIDR, _ := net.ParseCIDR("127.123.234.0/26") return serviceCIDR }(), + secondaryServiceCIDR: nil, }, { @@ -216,13 +222,14 @@ func TestAllocateOrOccupyCIDRSuccess(t *testing.T) { _, serviceCIDR, _ := net.ParseCIDR("127.123.234.0/26") return serviceCIDR }(), + secondaryServiceCIDR: nil, }, } // test function testFunc := func(tc testCase) { // Initialize the range allocator. - allocator, err := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDRs, tc.serviceCIDR, tc.subNetMaskSize, nil) + allocator, err := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDRs, tc.serviceCIDR, tc.secondaryServiceCIDR, tc.subNetMaskSize, nil) if err != nil { t.Errorf("%v: failed to create CIDRRangeAllocator with error %v", tc.description, err) return @@ -298,8 +305,9 @@ func TestAllocateOrOccupyCIDRFailure(t *testing.T) { _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/28") return []*net.IPNet{clusterCIDR} }(), - serviceCIDR: nil, - subNetMaskSize: 30, + serviceCIDR: nil, + secondaryServiceCIDR: nil, + subNetMaskSize: 30, allocatedCIDRs: map[int][]string{ 0: {"127.123.234.0/30", "127.123.234.4/30", "127.123.234.8/30", "127.123.234.12/30"}, }, @@ -308,7 +316,7 @@ func TestAllocateOrOccupyCIDRFailure(t *testing.T) { testFunc := func(tc testCase) { // Initialize the range allocator. - allocator, err := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDRs, tc.serviceCIDR, tc.subNetMaskSize, nil) + allocator, err := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDRs, tc.serviceCIDR, tc.secondaryServiceCIDR, tc.subNetMaskSize, nil) if err != nil { t.Logf("%v: failed to create CIDRRangeAllocator with error %v", tc.description, err) } @@ -369,6 +377,7 @@ type releaseTestCase struct { fakeNodeHandler *testutil.FakeNodeHandler clusterCIDRs []*net.IPNet serviceCIDR *net.IPNet + secondaryServiceCIDR *net.IPNet subNetMaskSize int expectedAllocatedCIDRFirstRound map[int]string expectedAllocatedCIDRSecondRound map[int]string @@ -394,8 +403,9 @@ func TestReleaseCIDRSuccess(t *testing.T) { _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/28") return []*net.IPNet{clusterCIDR} }(), - serviceCIDR: nil, - subNetMaskSize: 30, + serviceCIDR: nil, + secondaryServiceCIDR: nil, + subNetMaskSize: 30, allocatedCIDRs: map[int][]string{ 0: {"127.123.234.0/30", "127.123.234.4/30", "127.123.234.8/30", "127.123.234.12/30"}, }, @@ -423,8 +433,9 @@ func TestReleaseCIDRSuccess(t *testing.T) { _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/28") return []*net.IPNet{clusterCIDR} }(), - serviceCIDR: nil, - subNetMaskSize: 30, + serviceCIDR: nil, + secondaryServiceCIDR: nil, + subNetMaskSize: 30, allocatedCIDRs: map[int][]string{ 0: {"127.123.234.4/30", "127.123.234.8/30", "127.123.234.12/30"}, }, @@ -442,7 +453,7 @@ func TestReleaseCIDRSuccess(t *testing.T) { testFunc := func(tc releaseTestCase) { // Initialize the range allocator. - allocator, _ := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDRs, tc.serviceCIDR, tc.subNetMaskSize, nil) + allocator, _ := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDRs, tc.serviceCIDR, tc.secondaryServiceCIDR, tc.subNetMaskSize, nil) rangeAllocator, ok := allocator.(*rangeAllocator) if !ok { t.Logf("%v: found non-default implementation of CIDRAllocator, skipping white-box test...", tc.description) diff --git a/pkg/controller/nodeipam/node_ipam_controller.go b/pkg/controller/nodeipam/node_ipam_controller.go index 0540490fed7..48dabd15601 100644 --- a/pkg/controller/nodeipam/node_ipam_controller.go +++ b/pkg/controller/nodeipam/node_ipam_controller.go @@ -53,10 +53,11 @@ const ( type Controller struct { allocatorType ipam.CIDRAllocatorType - cloud cloudprovider.Interface - clusterCIDRs []*net.IPNet - serviceCIDR *net.IPNet - kubeClient clientset.Interface + cloud cloudprovider.Interface + clusterCIDRs []*net.IPNet + serviceCIDR *net.IPNet + secondaryServiceCIDR *net.IPNet + kubeClient clientset.Interface // Method for easy mocking in unittest. lookupIP func(host string) ([]net.IP, error) @@ -79,6 +80,7 @@ func NewNodeIpamController( kubeClient clientset.Interface, clusterCIDRs []*net.IPNet, serviceCIDR *net.IPNet, + secondaryServiceCIDR *net.IPNet, nodeCIDRMaskSize int, allocatorType ipam.CIDRAllocatorType) (*Controller, error) { @@ -119,12 +121,13 @@ func NewNodeIpamController( } ic := &Controller{ - cloud: cloud, - kubeClient: kubeClient, - lookupIP: net.LookupIP, - clusterCIDRs: clusterCIDRs, - serviceCIDR: serviceCIDR, - allocatorType: allocatorType, + cloud: cloud, + kubeClient: kubeClient, + lookupIP: net.LookupIP, + clusterCIDRs: clusterCIDRs, + serviceCIDR: serviceCIDR, + secondaryServiceCIDR: secondaryServiceCIDR, + allocatorType: allocatorType, } // TODO: Abstract this check into a generic controller manager should run method. @@ -132,7 +135,7 @@ func NewNodeIpamController( startLegacyIPAM(ic, nodeInformer, cloud, kubeClient, clusterCIDRs, serviceCIDR, nodeCIDRMaskSize) } else { var err error - ic.cidrAllocator, err = ipam.New(kubeClient, cloud, nodeInformer, ic.allocatorType, clusterCIDRs, ic.serviceCIDR, nodeCIDRMaskSize) + ic.cidrAllocator, err = ipam.New(kubeClient, cloud, nodeInformer, ic.allocatorType, clusterCIDRs, ic.serviceCIDR, ic.secondaryServiceCIDR, nodeCIDRMaskSize) if err != nil { return nil, err } diff --git a/pkg/controller/nodeipam/node_ipam_controller_test.go b/pkg/controller/nodeipam/node_ipam_controller_test.go index 49f18a11293..50d0b63a192 100644 --- a/pkg/controller/nodeipam/node_ipam_controller_test.go +++ b/pkg/controller/nodeipam/node_ipam_controller_test.go @@ -34,7 +34,7 @@ import ( netutils "k8s.io/utils/net" ) -func newTestNodeIpamController(clusterCIDR []*net.IPNet, serviceCIDR *net.IPNet, nodeCIDRMaskSize int, allocatorType ipam.CIDRAllocatorType) (*Controller, error) { +func newTestNodeIpamController(clusterCIDR []*net.IPNet, serviceCIDR *net.IPNet, secondaryServiceCIDR *net.IPNet, nodeCIDRMaskSize int, allocatorType ipam.CIDRAllocatorType) (*Controller, error) { clientSet := fake.NewSimpleClientset() fakeNodeHandler := &testutil.FakeNodeHandler{ Existing: []*v1.Node{ @@ -53,39 +53,45 @@ func newTestNodeIpamController(clusterCIDR []*net.IPNet, serviceCIDR *net.IPNet, fakeGCE := gce.NewFakeGCECloud(gce.DefaultTestClusterValues()) return NewNodeIpamController( fakeNodeInformer, fakeGCE, clientSet, - clusterCIDR, serviceCIDR, nodeCIDRMaskSize, allocatorType, + clusterCIDR, serviceCIDR, secondaryServiceCIDR, nodeCIDRMaskSize, allocatorType, ) } // TestNewNodeIpamControllerWithCIDRMasks tests if the controller can be // created with combinations of network CIDRs and masks. func TestNewNodeIpamControllerWithCIDRMasks(t *testing.T) { + emptyServiceCIDR := "" for _, tc := range []struct { - desc string - clusterCIDR string - serviceCIDR string - maskSize int - allocatorType ipam.CIDRAllocatorType - wantFatal bool + desc string + clusterCIDR string + serviceCIDR string + secondaryServiceCIDR string + maskSize int + allocatorType ipam.CIDRAllocatorType + wantFatal bool }{ - {"valid_range_allocator", "10.0.0.0/21", "10.1.0.0/21", 24, ipam.RangeAllocatorType, false}, - {"valid_range_allocator_dualstack", "10.0.0.0/21,2000::/10", "10.1.0.0/21", 24, ipam.RangeAllocatorType, false}, - {"valid_cloud_allocator", "10.0.0.0/21", "10.1.0.0/21", 24, ipam.CloudAllocatorType, false}, - {"valid_ipam_from_cluster", "10.0.0.0/21", "10.1.0.0/21", 24, ipam.IPAMFromClusterAllocatorType, false}, - {"valid_ipam_from_cloud", "10.0.0.0/21", "10.1.0.0/21", 24, ipam.IPAMFromCloudAllocatorType, false}, - {"valid_skip_cluster_CIDR_validation_for_cloud_allocator", "invalid", "10.1.0.0/21", 24, ipam.CloudAllocatorType, false}, - {"invalid_cluster_CIDR", "invalid", "10.1.0.0/21", 24, ipam.IPAMFromClusterAllocatorType, true}, - {"valid_CIDR_smaller_than_mask_cloud_allocator", "10.0.0.0/26", "10.1.0.0/21", 24, ipam.CloudAllocatorType, false}, - {"invalid_CIDR_smaller_than_mask_other_allocators", "10.0.0.0/26", "10.1.0.0/21", 24, ipam.IPAMFromCloudAllocatorType, true}, - {"invalid_serviceCIDR_contains_clusterCIDR", "10.0.0.0/23", "10.0.0.0/21", 24, ipam.IPAMFromClusterAllocatorType, true}, + {"valid_range_allocator", "10.0.0.0/21", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.RangeAllocatorType, false}, + + {"valid_range_allocator_dualstack", "10.0.0.0/21,2000::/10", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.RangeAllocatorType, false}, + {"valid_range_allocator_dualstack_dualstackservice", "10.0.0.0/21,2000::/10", "10.1.0.0/21", "3000::/10", 24, ipam.RangeAllocatorType, false}, + + {"valid_cloud_allocator", "10.0.0.0/21", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.CloudAllocatorType, false}, + {"valid_ipam_from_cluster", "10.0.0.0/21", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.IPAMFromClusterAllocatorType, false}, + {"valid_ipam_from_cloud", "10.0.0.0/21", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.IPAMFromCloudAllocatorType, false}, + {"valid_skip_cluster_CIDR_validation_for_cloud_allocator", "invalid", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.CloudAllocatorType, false}, + {"invalid_cluster_CIDR", "invalid", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.IPAMFromClusterAllocatorType, true}, + {"valid_CIDR_smaller_than_mask_cloud_allocator", "10.0.0.0/26", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.CloudAllocatorType, false}, + {"invalid_CIDR_smaller_than_mask_other_allocators", "10.0.0.0/26", "10.1.0.0/21", emptyServiceCIDR, 24, ipam.IPAMFromCloudAllocatorType, true}, + {"invalid_serviceCIDR_contains_clusterCIDR", "10.0.0.0/23", "10.0.0.0/21", emptyServiceCIDR, 24, ipam.IPAMFromClusterAllocatorType, true}, } { t.Run(tc.desc, func(t *testing.T) { clusterCidrs, _ := netutils.ParseCIDRs(strings.Split(tc.clusterCIDR, ",")) _, serviceCIDRIpNet, _ := net.ParseCIDR(tc.serviceCIDR) + _, secondaryServiceCIDRIpNet, _ := net.ParseCIDR(tc.secondaryServiceCIDR) if os.Getenv("EXIT_ON_FATAL") == "1" { // This is the subprocess which runs the actual code. - newTestNodeIpamController(clusterCidrs, serviceCIDRIpNet, tc.maskSize, tc.allocatorType) + newTestNodeIpamController(clusterCidrs, serviceCIDRIpNet, secondaryServiceCIDRIpNet, tc.maskSize, tc.allocatorType) return } // This is the host process that monitors the exit code of the subprocess. diff --git a/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/types.go b/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/types.go index db869f34b6d..dee7bb15693 100644 --- a/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/types.go +++ b/staging/src/k8s.io/kube-controller-manager/config/v1alpha1/types.go @@ -361,6 +361,8 @@ type NamespaceControllerConfiguration struct { type NodeIPAMControllerConfiguration struct { // serviceCIDR is CIDR Range for Services in cluster. ServiceCIDR string + // secondaryServiceCIDR is CIDR Range for Services in cluster. This is used in dual stack clusters. SecondaryServiceCIDR must be of different IP family than ServiceCIDR + SecondaryServiceCIDR string // NodeCIDRMaskSize is the mask size for node cidr in cluster. NodeCIDRMaskSize int32 } diff --git a/test/integration/ipamperf/ipam_test.go b/test/integration/ipamperf/ipam_test.go index 09d69f44aa6..7b9bbd236cc 100644 --- a/test/integration/ipamperf/ipam_test.go +++ b/test/integration/ipamperf/ipam_test.go @@ -52,7 +52,7 @@ func setupAllocator(apiURL string, config *Config, clusterCIDR, serviceCIDR *net sharedInformer := informers.NewSharedInformerFactory(clientSet, 1*time.Hour) ipamController, err := nodeipam.NewNodeIpamController( sharedInformer.Core().V1().Nodes(), config.Cloud, clientSet, - []*net.IPNet{clusterCIDR}, serviceCIDR, subnetMaskSize, config.AllocatorType, + []*net.IPNet{clusterCIDR}, serviceCIDR, nil, subnetMaskSize, config.AllocatorType, ) if err != nil { return nil, shutdownFunc, err From c27e0b029d328552cc3ef0661f16a5ad3c422fb8 Mon Sep 17 00:00:00 2001 From: "Khaled Henidak(Kal)" Date: Wed, 28 Aug 2019 16:11:46 +0000 Subject: [PATCH 4/4] phase 2: generated items --- api/openapi-spec/swagger.json | 4 + cmd/kube-apiserver/app/options/BUILD | 5 + pkg/apis/core/v1/BUILD | 6 + pkg/apis/core/v1/zz_generated.conversion.go | 2 + pkg/apis/core/zz_generated.deepcopy.go | 5 + pkg/controller/endpoint/BUILD | 6 + .../v1alpha1/zz_generated.conversion.go | 2 + pkg/registry/core/service/BUILD | 6 + .../core/service/ipallocator/controller/BUILD | 6 + pkg/registry/core/service/storage/BUILD | 7 +- .../src/k8s.io/api/core/v1/generated.pb.go | 1733 +++++++++-------- .../src/k8s.io/api/core/v1/generated.proto | 10 + .../core/v1/types_swagger_doc_generated.go | 1 + .../api/core/v1/zz_generated.deepcopy.go | 5 + .../api/testdata/HEAD/core.v1.Service.json | 3 +- .../api/testdata/HEAD/core.v1.Service.pb | Bin 368 -> 401 bytes .../api/testdata/HEAD/core.v1.Service.yaml | 1 + 17 files changed, 957 insertions(+), 845 deletions(-) diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index b84758aee53..be57b336d0d 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -11403,6 +11403,10 @@ "format": "int32", "type": "integer" }, + "ipFamily": { + "description": "ipFamily specifies whether this Service has a preference for a particular IP family (e.g. IPv4 vs. IPv6). If a specific IP family is requested, the clusterIP field will be allocated from that family, if it is available in the cluster. If no IP family is requested, the cluster's primary IP family will be used. Other IP fields (loadBalancerIP, loadBalancerSourceRanges, externalIPs) and controllers which allocate external load-balancers should use the same IP family. Endpoints for this Service will be of this family. This field is immutable after creation. Assigning a ServiceIPFamily not available in the cluster (e.g. IPv6 in IPv4 only cluster) is an error condition and will fail during clusterIP assignment.", + "type": "string" + }, "loadBalancerIP": { "description": "Only applies to Service Type: LoadBalancer LoadBalancer will get created with the IP specified in this field. This feature depends on whether the underlying cloud-provider supports specifying the loadBalancerIP when a load balancer is created. This field will be ignored if the cloud-provider does not support the feature.", "type": "string" diff --git a/cmd/kube-apiserver/app/options/BUILD b/cmd/kube-apiserver/app/options/BUILD index 01569788ae5..3ab3a5d5a4c 100644 --- a/cmd/kube-apiserver/app/options/BUILD +++ b/cmd/kube-apiserver/app/options/BUILD @@ -35,6 +35,7 @@ go_library( "//staging/src/k8s.io/component-base/cli/globalflag:go_default_library", "//staging/src/k8s.io/kube-aggregator/pkg/apiserver/scheme:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/utils/net:go_default_library", ], ) @@ -43,22 +44,26 @@ go_test( srcs = [ "globalflags_test.go", "options_test.go", + "validation_test.go", ], embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", + "//pkg/features:go_default_library", "//pkg/kubeapiserver/options:go_default_library", "//pkg/kubelet/client:go_default_library", "//pkg/master/reconcilers:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/plugin/pkg/audit/buffered:go_default_library", "//staging/src/k8s.io/apiserver/plugin/pkg/audit/dynamic:go_default_library", "//staging/src/k8s.io/apiserver/plugin/pkg/audit/truncate:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//staging/src/k8s.io/component-base/cli/globalflag:go_default_library", + "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", "//vendor/github.com/spf13/pflag:go_default_library", ], ) diff --git a/pkg/apis/core/v1/BUILD b/pkg/apis/core/v1/BUILD index 7226462bbed..53cdd374782 100644 --- a/pkg/apis/core/v1/BUILD +++ b/pkg/apis/core/v1/BUILD @@ -15,6 +15,7 @@ go_library( deps = [ "//pkg/apis/apps:go_default_library", "//pkg/apis/core:go_default_library", + "//pkg/features:go_default_library", "//pkg/util/parsers:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", @@ -25,6 +26,8 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//vendor/k8s.io/utils/net:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", ], ) @@ -42,6 +45,7 @@ go_test( "//pkg/apis/apps:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/fuzzer:go_default_library", + "//pkg/features:go_default_library", "//staging/src/k8s.io/api/apps/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/apitesting/fuzzer:go_default_library", @@ -52,6 +56,8 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", ], ) diff --git a/pkg/apis/core/v1/zz_generated.conversion.go b/pkg/apis/core/v1/zz_generated.conversion.go index 116f3457adc..698d0767f1d 100644 --- a/pkg/apis/core/v1/zz_generated.conversion.go +++ b/pkg/apis/core/v1/zz_generated.conversion.go @@ -7236,6 +7236,7 @@ func autoConvert_v1_ServiceSpec_To_core_ServiceSpec(in *v1.ServiceSpec, out *cor out.HealthCheckNodePort = in.HealthCheckNodePort out.PublishNotReadyAddresses = in.PublishNotReadyAddresses out.SessionAffinityConfig = (*core.SessionAffinityConfig)(unsafe.Pointer(in.SessionAffinityConfig)) + out.IPFamily = (*core.IPFamily)(unsafe.Pointer(in.IPFamily)) return nil } @@ -7258,6 +7259,7 @@ func autoConvert_core_ServiceSpec_To_v1_ServiceSpec(in *core.ServiceSpec, out *v out.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyType(in.ExternalTrafficPolicy) out.HealthCheckNodePort = in.HealthCheckNodePort out.PublishNotReadyAddresses = in.PublishNotReadyAddresses + out.IPFamily = (*v1.IPFamily)(unsafe.Pointer(in.IPFamily)) return nil } diff --git a/pkg/apis/core/zz_generated.deepcopy.go b/pkg/apis/core/zz_generated.deepcopy.go index c01599322f2..3c1a0063cf7 100644 --- a/pkg/apis/core/zz_generated.deepcopy.go +++ b/pkg/apis/core/zz_generated.deepcopy.go @@ -5127,6 +5127,11 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.IPFamily != nil { + in, out := &in.IPFamily, &out.IPFamily + *out = new(IPFamily) + **out = **in + } return } diff --git a/pkg/controller/endpoint/BUILD b/pkg/controller/endpoint/BUILD index d8d39d4a451..211e6481a85 100644 --- a/pkg/controller/endpoint/BUILD +++ b/pkg/controller/endpoint/BUILD @@ -19,6 +19,7 @@ go_library( "//pkg/api/v1/pod:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/controller:go_default_library", + "//pkg/features:go_default_library", "//pkg/util/metrics:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library", @@ -28,6 +29,7 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library", @@ -38,6 +40,7 @@ go_library( "//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/util/workqueue:go_default_library", "//vendor/k8s.io/klog:go_default_library", + "//vendor/k8s.io/utils/net:go_default_library", ], ) @@ -53,6 +56,7 @@ go_test( "//pkg/api/v1/endpoints:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/controller:go_default_library", + "//pkg/features:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", @@ -60,11 +64,13 @@ go_test( "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/rest:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/util/testing:go_default_library", + "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", ], ) diff --git a/pkg/controller/nodeipam/config/v1alpha1/zz_generated.conversion.go b/pkg/controller/nodeipam/config/v1alpha1/zz_generated.conversion.go index bda86db7769..b738642d7c1 100644 --- a/pkg/controller/nodeipam/config/v1alpha1/zz_generated.conversion.go +++ b/pkg/controller/nodeipam/config/v1alpha1/zz_generated.conversion.go @@ -92,12 +92,14 @@ func Convert_v1_GroupResource_To_v1alpha1_GroupResource(in *v1.GroupResource, ou func autoConvert_v1alpha1_NodeIPAMControllerConfiguration_To_config_NodeIPAMControllerConfiguration(in *v1alpha1.NodeIPAMControllerConfiguration, out *config.NodeIPAMControllerConfiguration, s conversion.Scope) error { out.ServiceCIDR = in.ServiceCIDR + out.SecondaryServiceCIDR = in.SecondaryServiceCIDR out.NodeCIDRMaskSize = in.NodeCIDRMaskSize return nil } func autoConvert_config_NodeIPAMControllerConfiguration_To_v1alpha1_NodeIPAMControllerConfiguration(in *config.NodeIPAMControllerConfiguration, out *v1alpha1.NodeIPAMControllerConfiguration, s conversion.Scope) error { out.ServiceCIDR = in.ServiceCIDR + out.SecondaryServiceCIDR = in.SecondaryServiceCIDR out.NodeCIDRMaskSize = in.NodeCIDRMaskSize return nil } diff --git a/pkg/registry/core/service/BUILD b/pkg/registry/core/service/BUILD index 2eeaa2a3057..bb5c9d99943 100644 --- a/pkg/registry/core/service/BUILD +++ b/pkg/registry/core/service/BUILD @@ -19,12 +19,14 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/validation:go_default_library", "//pkg/capabilities:go_default_library", + "//pkg/features:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/net:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/proxy:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", ], ) @@ -35,12 +37,16 @@ go_test( deps = [ "//pkg/apis/core:go_default_library", "//pkg/apis/core/install:go_default_library", + "//pkg/features:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", ], ) diff --git a/pkg/registry/core/service/ipallocator/controller/BUILD b/pkg/registry/core/service/ipallocator/controller/BUILD index 8921bbc23ad..959f42ba5f6 100644 --- a/pkg/registry/core/service/ipallocator/controller/BUILD +++ b/pkg/registry/core/service/ipallocator/controller/BUILD @@ -14,6 +14,7 @@ go_library( "//pkg/api/legacyscheme:go_default_library", "//pkg/apis/core:go_default_library", "//pkg/apis/core/v1/helper:go_default_library", + "//pkg/features:go_default_library", "//pkg/registry/core/rangeallocation:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", @@ -21,9 +22,11 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/util/retry:go_default_library", + "//vendor/k8s.io/utils/net:go_default_library", ], ) @@ -33,10 +36,13 @@ go_test( embed = [":go_default_library"], deps = [ "//pkg/apis/core:go_default_library", + "//pkg/features:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", + "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", ], ) diff --git a/pkg/registry/core/service/storage/BUILD b/pkg/registry/core/service/storage/BUILD index 8b043e6fad3..e4902e6da50 100644 --- a/pkg/registry/core/service/storage/BUILD +++ b/pkg/registry/core/service/storage/BUILD @@ -16,7 +16,7 @@ go_test( deps = [ "//pkg/api/service:go_default_library", "//pkg/apis/core:go_default_library", - "//pkg/apis/core/helper:go_default_library", + "//pkg/features:go_default_library", "//pkg/registry/core/endpoint/storage:go_default_library", "//pkg/registry/core/pod/storage:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", @@ -40,6 +40,8 @@ go_test( "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage/etcd3/testing:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/dryrun:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", + "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library", ], ) @@ -55,6 +57,7 @@ go_library( "//pkg/apis/core:go_default_library", "//pkg/apis/core/helper:go_default_library", "//pkg/apis/core/validation:go_default_library", + "//pkg/features:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", "//pkg/printers/storage:go_default_library", @@ -75,7 +78,9 @@ go_library( "//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/dryrun:go_default_library", + "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/klog:go_default_library", + "//vendor/k8s.io/utils/net:go_default_library", ], ) diff --git a/staging/src/k8s.io/api/core/v1/generated.pb.go b/staging/src/k8s.io/api/core/v1/generated.pb.go index 7e745891dfe..0492962575b 100644 --- a/staging/src/k8s.io/api/core/v1/generated.pb.go +++ b/staging/src/k8s.io/api/core/v1/generated.pb.go @@ -5971,849 +5971,851 @@ func init() { } var fileDescriptor_83c10c24ec417dc9 = []byte{ - // 13467 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x7d, 0x6b, 0x70, 0x64, 0x57, - 0x5a, 0xd8, 0xde, 0x6e, 0x3d, 0xba, 0x3f, 0xbd, 0xcf, 0x3c, 0xac, 0x91, 0x3d, 0xa3, 0xf1, 0x9d, - 0xdd, 0xf1, 0x78, 0x6d, 0x6b, 0xd6, 0x63, 0x7b, 0x6d, 0xd6, 0xbb, 0x06, 0x49, 0x2d, 0xcd, 0xc8, - 0x33, 0xd2, 0xb4, 0x4f, 0x6b, 0x66, 0x76, 0x8d, 0x77, 0xd9, 0xab, 0xbe, 0x47, 0xd2, 0xb5, 0xba, - 0xef, 0x6d, 0xdf, 0x7b, 0x5b, 0x1a, 0x39, 0x50, 0x21, 0x4b, 0x78, 0x6c, 0x80, 0xd4, 0x56, 0x42, - 0xe5, 0x01, 0x14, 0xa9, 0x22, 0xa4, 0x80, 0x40, 0x52, 0x21, 0x4b, 0x80, 0xb0, 0x24, 0x21, 0x90, - 0xa4, 0x48, 0x7e, 0x6c, 0x48, 0x2a, 0xa9, 0xa5, 0x8a, 0x8a, 0x02, 0x43, 0x2a, 0x14, 0x3f, 0x02, - 0x54, 0xe0, 0x4f, 0x14, 0x2a, 0xa4, 0xce, 0xf3, 0x9e, 0x73, 0xfb, 0xde, 0xee, 0xd6, 0x58, 0xa3, - 0x35, 0x5b, 0xfe, 0xd7, 0x7d, 0xbe, 0xef, 0x7c, 0xe7, 0xdc, 0xf3, 0xfc, 0xce, 0xf7, 0x84, 0x57, - 0x77, 0x5e, 0x89, 0xe6, 0xbc, 0xe0, 0xea, 0x4e, 0x7b, 0x83, 0x84, 0x3e, 0x89, 0x49, 0x74, 0x75, - 0x97, 0xf8, 0x6e, 0x10, 0x5e, 0x15, 0x00, 0xa7, 0xe5, 0x5d, 0xad, 0x07, 0x21, 0xb9, 0xba, 0xfb, - 0xfc, 0xd5, 0x2d, 0xe2, 0x93, 0xd0, 0x89, 0x89, 0x3b, 0xd7, 0x0a, 0x83, 0x38, 0x40, 0x88, 0xe3, - 0xcc, 0x39, 0x2d, 0x6f, 0x8e, 0xe2, 0xcc, 0xed, 0x3e, 0x3f, 0xf3, 0xdc, 0x96, 0x17, 0x6f, 0xb7, - 0x37, 0xe6, 0xea, 0x41, 0xf3, 0xea, 0x56, 0xb0, 0x15, 0x5c, 0x65, 0xa8, 0x1b, 0xed, 0x4d, 0xf6, - 0x8f, 0xfd, 0x61, 0xbf, 0x38, 0x89, 0x99, 0x17, 0x93, 0x66, 0x9a, 0x4e, 0x7d, 0xdb, 0xf3, 0x49, - 0xb8, 0x7f, 0xb5, 0xb5, 0xb3, 0xc5, 0xda, 0x0d, 0x49, 0x14, 0xb4, 0xc3, 0x3a, 0x49, 0x37, 0xdc, - 0xb5, 0x56, 0x74, 0xb5, 0x49, 0x62, 0x27, 0xa3, 0xbb, 0x33, 0x57, 0xf3, 0x6a, 0x85, 0x6d, 0x3f, - 0xf6, 0x9a, 0x9d, 0xcd, 0x7c, 0xbc, 0x57, 0x85, 0xa8, 0xbe, 0x4d, 0x9a, 0x4e, 0x47, 0xbd, 0x17, - 0xf2, 0xea, 0xb5, 0x63, 0xaf, 0x71, 0xd5, 0xf3, 0xe3, 0x28, 0x0e, 0xd3, 0x95, 0xec, 0xaf, 0x59, - 0x70, 0x71, 0xfe, 0x5e, 0x6d, 0xa9, 0xe1, 0x44, 0xb1, 0x57, 0x5f, 0x68, 0x04, 0xf5, 0x9d, 0x5a, - 0x1c, 0x84, 0xe4, 0x6e, 0xd0, 0x68, 0x37, 0x49, 0x8d, 0x0d, 0x04, 0x7a, 0x16, 0x4a, 0xbb, 0xec, - 0xff, 0x4a, 0x65, 0xda, 0xba, 0x68, 0x5d, 0x29, 0x2f, 0x4c, 0xfe, 0xc6, 0xc1, 0xec, 0x87, 0x1e, - 0x1c, 0xcc, 0x96, 0xee, 0x8a, 0x72, 0xac, 0x30, 0xd0, 0x65, 0x18, 0xda, 0x8c, 0xd6, 0xf7, 0x5b, - 0x64, 0xba, 0xc0, 0x70, 0xc7, 0x05, 0xee, 0xd0, 0x72, 0x8d, 0x96, 0x62, 0x01, 0x45, 0x57, 0xa1, - 0xdc, 0x72, 0xc2, 0xd8, 0x8b, 0xbd, 0xc0, 0x9f, 0x2e, 0x5e, 0xb4, 0xae, 0x0c, 0x2e, 0x4c, 0x09, - 0xd4, 0x72, 0x55, 0x02, 0x70, 0x82, 0x43, 0xbb, 0x11, 0x12, 0xc7, 0xbd, 0xed, 0x37, 0xf6, 0xa7, - 0x07, 0x2e, 0x5a, 0x57, 0x4a, 0x49, 0x37, 0xb0, 0x28, 0xc7, 0x0a, 0xc3, 0xfe, 0xe1, 0x02, 0x94, - 0xe6, 0x37, 0x37, 0x3d, 0xdf, 0x8b, 0xf7, 0xd1, 0x5d, 0x18, 0xf5, 0x03, 0x97, 0xc8, 0xff, 0xec, - 0x2b, 0x46, 0xae, 0x5d, 0x9c, 0xeb, 0x5c, 0x4a, 0x73, 0x6b, 0x1a, 0xde, 0xc2, 0xe4, 0x83, 0x83, - 0xd9, 0x51, 0xbd, 0x04, 0x1b, 0x74, 0x10, 0x86, 0x91, 0x56, 0xe0, 0x2a, 0xb2, 0x05, 0x46, 0x76, - 0x36, 0x8b, 0x6c, 0x35, 0x41, 0x5b, 0x98, 0x78, 0x70, 0x30, 0x3b, 0xa2, 0x15, 0x60, 0x9d, 0x08, - 0xda, 0x80, 0x09, 0xfa, 0xd7, 0x8f, 0x3d, 0x45, 0xb7, 0xc8, 0xe8, 0x5e, 0xca, 0xa3, 0xab, 0xa1, - 0x2e, 0x9c, 0x7a, 0x70, 0x30, 0x3b, 0x91, 0x2a, 0xc4, 0x69, 0x82, 0xf6, 0xbb, 0x30, 0x3e, 0x1f, - 0xc7, 0x4e, 0x7d, 0x9b, 0xb8, 0x7c, 0x06, 0xd1, 0x8b, 0x30, 0xe0, 0x3b, 0x4d, 0x22, 0xe6, 0xf7, - 0xa2, 0x18, 0xd8, 0x81, 0x35, 0xa7, 0x49, 0x0e, 0x0f, 0x66, 0x27, 0xef, 0xf8, 0xde, 0x3b, 0x6d, - 0xb1, 0x2a, 0x68, 0x19, 0x66, 0xd8, 0xe8, 0x1a, 0x80, 0x4b, 0x76, 0xbd, 0x3a, 0xa9, 0x3a, 0xf1, - 0xb6, 0x98, 0x6f, 0x24, 0xea, 0x42, 0x45, 0x41, 0xb0, 0x86, 0x65, 0xdf, 0x87, 0xf2, 0xfc, 0x6e, - 0xe0, 0xb9, 0xd5, 0xc0, 0x8d, 0xd0, 0x0e, 0x4c, 0xb4, 0x42, 0xb2, 0x49, 0x42, 0x55, 0x34, 0x6d, - 0x5d, 0x2c, 0x5e, 0x19, 0xb9, 0x76, 0x25, 0xf3, 0x63, 0x4d, 0xd4, 0x25, 0x3f, 0x0e, 0xf7, 0x17, - 0x1e, 0x13, 0xed, 0x4d, 0xa4, 0xa0, 0x38, 0x4d, 0xd9, 0xfe, 0x37, 0x05, 0x38, 0x33, 0xff, 0x6e, - 0x3b, 0x24, 0x15, 0x2f, 0xda, 0x49, 0xaf, 0x70, 0xd7, 0x8b, 0x76, 0xd6, 0x92, 0x11, 0x50, 0x4b, - 0xab, 0x22, 0xca, 0xb1, 0xc2, 0x40, 0xcf, 0xc1, 0x30, 0xfd, 0x7d, 0x07, 0xaf, 0x88, 0x4f, 0x3e, - 0x25, 0x90, 0x47, 0x2a, 0x4e, 0xec, 0x54, 0x38, 0x08, 0x4b, 0x1c, 0xb4, 0x0a, 0x23, 0x75, 0xb6, - 0x21, 0xb7, 0x56, 0x03, 0x97, 0xb0, 0xc9, 0x2c, 0x2f, 0x3c, 0x43, 0xd1, 0x17, 0x93, 0xe2, 0xc3, - 0x83, 0xd9, 0x69, 0xde, 0x37, 0x41, 0x42, 0x83, 0x61, 0xbd, 0x3e, 0xb2, 0xd5, 0xfe, 0x1a, 0x60, - 0x94, 0x20, 0x63, 0x6f, 0x5d, 0xd1, 0xb6, 0xca, 0x20, 0xdb, 0x2a, 0xa3, 0xd9, 0xdb, 0x04, 0x3d, - 0x0f, 0x03, 0x3b, 0x9e, 0xef, 0x4e, 0x0f, 0x31, 0x5a, 0xe7, 0xe9, 0x9c, 0xdf, 0xf4, 0x7c, 0xf7, - 0xf0, 0x60, 0x76, 0xca, 0xe8, 0x0e, 0x2d, 0xc4, 0x0c, 0xd5, 0xfe, 0x13, 0x0b, 0x66, 0x19, 0x6c, - 0xd9, 0x6b, 0x90, 0x2a, 0x09, 0x23, 0x2f, 0x8a, 0x89, 0x1f, 0x1b, 0x03, 0x7a, 0x0d, 0x20, 0x22, - 0xf5, 0x90, 0xc4, 0xda, 0x90, 0xaa, 0x85, 0x51, 0x53, 0x10, 0xac, 0x61, 0xd1, 0x03, 0x21, 0xda, - 0x76, 0x42, 0xb6, 0xbe, 0xc4, 0xc0, 0xaa, 0x03, 0xa1, 0x26, 0x01, 0x38, 0xc1, 0x31, 0x0e, 0x84, - 0x62, 0xaf, 0x03, 0x01, 0x7d, 0x0a, 0x26, 0x92, 0xc6, 0xa2, 0x96, 0x53, 0x97, 0x03, 0xc8, 0xb6, - 0x4c, 0xcd, 0x04, 0xe1, 0x34, 0xae, 0xfd, 0x0f, 0x2d, 0xb1, 0x78, 0xe8, 0x57, 0xbf, 0xcf, 0xbf, - 0xd5, 0xfe, 0x25, 0x0b, 0x86, 0x17, 0x3c, 0xdf, 0xf5, 0xfc, 0x2d, 0xf4, 0x79, 0x28, 0xd1, 0xbb, - 0xc9, 0x75, 0x62, 0x47, 0x9c, 0x7b, 0x1f, 0xd3, 0xf6, 0x96, 0xba, 0x2a, 0xe6, 0x5a, 0x3b, 0x5b, - 0xb4, 0x20, 0x9a, 0xa3, 0xd8, 0x74, 0xb7, 0xdd, 0xde, 0x78, 0x9b, 0xd4, 0xe3, 0x55, 0x12, 0x3b, - 0xc9, 0xe7, 0x24, 0x65, 0x58, 0x51, 0x45, 0x37, 0x61, 0x28, 0x76, 0xc2, 0x2d, 0x12, 0x8b, 0x03, - 0x30, 0xf3, 0xa0, 0xe2, 0x35, 0x31, 0xdd, 0x91, 0xc4, 0xaf, 0x93, 0xe4, 0x5a, 0x58, 0x67, 0x55, - 0xb1, 0x20, 0x61, 0xff, 0xe0, 0x30, 0x9c, 0x5b, 0xac, 0xad, 0xe4, 0xac, 0xab, 0xcb, 0x30, 0xe4, - 0x86, 0xde, 0x2e, 0x09, 0xc5, 0x38, 0x2b, 0x2a, 0x15, 0x56, 0x8a, 0x05, 0x14, 0xbd, 0x02, 0xa3, - 0xfc, 0x42, 0xba, 0xe1, 0xf8, 0x6e, 0x43, 0x0e, 0xf1, 0x69, 0x81, 0x3d, 0x7a, 0x57, 0x83, 0x61, - 0x03, 0xf3, 0x88, 0x8b, 0xea, 0x72, 0x6a, 0x33, 0xe6, 0x5d, 0x76, 0x5f, 0xb4, 0x60, 0x92, 0x37, - 0x33, 0x1f, 0xc7, 0xa1, 0xb7, 0xd1, 0x8e, 0x49, 0x34, 0x3d, 0xc8, 0x4e, 0xba, 0xc5, 0xac, 0xd1, - 0xca, 0x1d, 0x81, 0xb9, 0xbb, 0x29, 0x2a, 0xfc, 0x10, 0x9c, 0x16, 0xed, 0x4e, 0xa6, 0xc1, 0xb8, - 0xa3, 0x59, 0xf4, 0x5d, 0x16, 0xcc, 0xd4, 0x03, 0x3f, 0x0e, 0x83, 0x46, 0x83, 0x84, 0xd5, 0xf6, - 0x46, 0xc3, 0x8b, 0xb6, 0xf9, 0x3a, 0xc5, 0x64, 0x93, 0x9d, 0x04, 0x39, 0x73, 0xa8, 0x90, 0xc4, - 0x1c, 0x5e, 0x78, 0x70, 0x30, 0x3b, 0xb3, 0x98, 0x4b, 0x0a, 0x77, 0x69, 0x06, 0xed, 0x00, 0xa2, - 0x57, 0x69, 0x2d, 0x76, 0xb6, 0x48, 0xd2, 0xf8, 0x70, 0xff, 0x8d, 0x9f, 0x7d, 0x70, 0x30, 0x8b, - 0xd6, 0x3a, 0x48, 0xe0, 0x0c, 0xb2, 0xe8, 0x1d, 0x38, 0x4d, 0x4b, 0x3b, 0xbe, 0xb5, 0xd4, 0x7f, - 0x73, 0xd3, 0x0f, 0x0e, 0x66, 0x4f, 0xaf, 0x65, 0x10, 0xc1, 0x99, 0xa4, 0xd1, 0x77, 0x5a, 0x70, - 0x2e, 0xf9, 0xfc, 0xa5, 0xfb, 0x2d, 0xc7, 0x77, 0x93, 0x86, 0xcb, 0xfd, 0x37, 0x4c, 0xcf, 0xe4, - 0x73, 0x8b, 0x79, 0x94, 0x70, 0x7e, 0x23, 0x33, 0x8b, 0x70, 0x26, 0x73, 0xb5, 0xa0, 0x49, 0x28, - 0xee, 0x10, 0xce, 0x05, 0x95, 0x31, 0xfd, 0x89, 0x4e, 0xc3, 0xe0, 0xae, 0xd3, 0x68, 0x8b, 0x8d, - 0x82, 0xf9, 0x9f, 0x4f, 0x14, 0x5e, 0xb1, 0xec, 0x7f, 0x5b, 0x84, 0x89, 0xc5, 0xda, 0xca, 0x43, - 0xed, 0x42, 0xfd, 0x1a, 0x2a, 0x74, 0xbd, 0x86, 0x92, 0x4b, 0xad, 0x98, 0x7b, 0xa9, 0xfd, 0xe5, - 0x8c, 0x2d, 0x34, 0xc0, 0xb6, 0xd0, 0x37, 0xe5, 0x6c, 0xa1, 0x63, 0xde, 0x38, 0xbb, 0x39, 0xab, - 0x68, 0x90, 0x4d, 0x66, 0x26, 0xc7, 0x72, 0x2b, 0xa8, 0x3b, 0x8d, 0xf4, 0xd1, 0x77, 0xc4, 0xa5, - 0x74, 0x3c, 0xf3, 0x58, 0x87, 0xd1, 0x45, 0xa7, 0xe5, 0x6c, 0x78, 0x0d, 0x2f, 0xf6, 0x48, 0x84, - 0x9e, 0x82, 0xa2, 0xe3, 0xba, 0x8c, 0xdb, 0x2a, 0x2f, 0x9c, 0x79, 0x70, 0x30, 0x5b, 0x9c, 0x77, - 0xe9, 0xb5, 0x0f, 0x0a, 0x6b, 0x1f, 0x53, 0x0c, 0xf4, 0x51, 0x18, 0x70, 0xc3, 0xa0, 0x35, 0x5d, - 0x60, 0x98, 0x74, 0xd7, 0x0d, 0x54, 0xc2, 0xa0, 0x95, 0x42, 0x65, 0x38, 0xf6, 0xaf, 0x16, 0xe0, - 0x89, 0x45, 0xd2, 0xda, 0x5e, 0xae, 0xe5, 0x9c, 0xdf, 0x57, 0xa0, 0xd4, 0x0c, 0x7c, 0x2f, 0x0e, - 0xc2, 0x48, 0x34, 0xcd, 0x56, 0xc4, 0xaa, 0x28, 0xc3, 0x0a, 0x8a, 0x2e, 0xc2, 0x40, 0x2b, 0x61, - 0x2a, 0x47, 0x25, 0x43, 0xca, 0xd8, 0x49, 0x06, 0xa1, 0x18, 0xed, 0x88, 0x84, 0x62, 0xc5, 0x28, - 0x8c, 0x3b, 0x11, 0x09, 0x31, 0x83, 0x24, 0x37, 0x33, 0xbd, 0xb3, 0xc5, 0x09, 0x9d, 0xba, 0x99, - 0x29, 0x04, 0x6b, 0x58, 0xa8, 0x0a, 0xe5, 0x28, 0x35, 0xb3, 0x7d, 0x6d, 0xd3, 0x31, 0x76, 0x75, - 0xab, 0x99, 0x4c, 0x88, 0x18, 0x37, 0xca, 0x50, 0xcf, 0xab, 0xfb, 0x2b, 0x05, 0x40, 0x7c, 0x08, - 0xff, 0x82, 0x0d, 0xdc, 0x9d, 0xce, 0x81, 0xeb, 0x7f, 0x4b, 0x1c, 0xd7, 0xe8, 0xfd, 0xa9, 0x05, - 0x4f, 0x2c, 0x7a, 0xbe, 0x4b, 0xc2, 0x9c, 0x05, 0xf8, 0x68, 0xde, 0xb2, 0x47, 0x63, 0x1a, 0x8c, - 0x25, 0x36, 0x70, 0x0c, 0x4b, 0xcc, 0xfe, 0x23, 0x0b, 0x10, 0xff, 0xec, 0xf7, 0xdd, 0xc7, 0xde, - 0xe9, 0xfc, 0xd8, 0x63, 0x58, 0x16, 0xf6, 0x2d, 0x18, 0x5f, 0x6c, 0x78, 0xc4, 0x8f, 0x57, 0xaa, - 0x8b, 0x81, 0xbf, 0xe9, 0x6d, 0xa1, 0x4f, 0xc0, 0x78, 0xec, 0x35, 0x49, 0xd0, 0x8e, 0x6b, 0xa4, - 0x1e, 0xf8, 0xec, 0x25, 0x69, 0x5d, 0x19, 0x5c, 0x40, 0x0f, 0x0e, 0x66, 0xc7, 0xd7, 0x0d, 0x08, - 0x4e, 0x61, 0xda, 0xbf, 0x4d, 0xc7, 0x2f, 0x68, 0xb6, 0x02, 0x9f, 0xf8, 0xf1, 0x62, 0xe0, 0xbb, - 0x5c, 0xe2, 0xf0, 0x09, 0x18, 0x88, 0xe9, 0x78, 0xf0, 0xb1, 0xbb, 0x2c, 0x37, 0x0a, 0x1d, 0x85, - 0xc3, 0x83, 0xd9, 0xb3, 0x9d, 0x35, 0xd8, 0x38, 0xb1, 0x3a, 0xe8, 0x9b, 0x60, 0x28, 0x8a, 0x9d, - 0xb8, 0x1d, 0x89, 0xd1, 0x7c, 0x52, 0x8e, 0x66, 0x8d, 0x95, 0x1e, 0x1e, 0xcc, 0x4e, 0xa8, 0x6a, - 0xbc, 0x08, 0x8b, 0x0a, 0xe8, 0x69, 0x18, 0x6e, 0x92, 0x28, 0x72, 0xb6, 0xe4, 0x6d, 0x38, 0x21, - 0xea, 0x0e, 0xaf, 0xf2, 0x62, 0x2c, 0xe1, 0xe8, 0x12, 0x0c, 0x92, 0x30, 0x0c, 0x42, 0xb1, 0x47, - 0xc7, 0x04, 0xe2, 0xe0, 0x12, 0x2d, 0xc4, 0x1c, 0x66, 0xff, 0x47, 0x0b, 0x26, 0x54, 0x5f, 0x79, - 0x5b, 0x27, 0xf0, 0x2a, 0x78, 0x13, 0xa0, 0x2e, 0x3f, 0x30, 0x62, 0xb7, 0xc7, 0xc8, 0xb5, 0xcb, - 0x99, 0x17, 0x75, 0xc7, 0x30, 0x26, 0x94, 0x55, 0x51, 0x84, 0x35, 0x6a, 0xf6, 0xbf, 0xb0, 0xe0, - 0x54, 0xea, 0x8b, 0x6e, 0x79, 0x51, 0x8c, 0xde, 0xea, 0xf8, 0xaa, 0xb9, 0xfe, 0xbe, 0x8a, 0xd6, - 0x66, 0xdf, 0xa4, 0x96, 0xb2, 0x2c, 0xd1, 0xbe, 0xe8, 0x06, 0x0c, 0x7a, 0x31, 0x69, 0xca, 0x8f, - 0xb9, 0xd4, 0xf5, 0x63, 0x78, 0xaf, 0x92, 0x19, 0x59, 0xa1, 0x35, 0x31, 0x27, 0x60, 0xff, 0xcd, - 0x22, 0x94, 0xf9, 0xb2, 0x5d, 0x75, 0x5a, 0x27, 0x30, 0x17, 0x2b, 0x30, 0xc0, 0xa8, 0xf3, 0x8e, - 0x3f, 0x95, 0xdd, 0x71, 0xd1, 0x9d, 0x39, 0xfa, 0xe4, 0xe7, 0xcc, 0x91, 0xba, 0x1a, 0x68, 0x11, - 0x66, 0x24, 0x90, 0x03, 0xb0, 0xe1, 0xf9, 0x4e, 0xb8, 0x4f, 0xcb, 0xa6, 0x8b, 0x8c, 0xe0, 0x73, - 0xdd, 0x09, 0x2e, 0x28, 0x7c, 0x4e, 0x56, 0xf5, 0x35, 0x01, 0x60, 0x8d, 0xe8, 0xcc, 0xcb, 0x50, - 0x56, 0xc8, 0x47, 0xe1, 0x71, 0x66, 0x3e, 0x05, 0x13, 0xa9, 0xb6, 0x7a, 0x55, 0x1f, 0xd5, 0x59, - 0xa4, 0x5f, 0x66, 0xa7, 0x80, 0xe8, 0xf5, 0x92, 0xbf, 0x2b, 0x4e, 0xd1, 0x77, 0xe1, 0x74, 0x23, - 0xe3, 0x70, 0x12, 0x53, 0xd5, 0xff, 0x61, 0xf6, 0x84, 0xf8, 0xec, 0xd3, 0x59, 0x50, 0x9c, 0xd9, - 0x06, 0xbd, 0xf6, 0x83, 0x16, 0x5d, 0xf3, 0x4e, 0x43, 0xe7, 0xa0, 0x6f, 0x8b, 0x32, 0xac, 0xa0, - 0xf4, 0x08, 0x3b, 0xad, 0x3a, 0x7f, 0x93, 0xec, 0xd7, 0x48, 0x83, 0xd4, 0xe3, 0x20, 0xfc, 0xba, - 0x76, 0xff, 0x3c, 0x1f, 0x7d, 0x7e, 0x02, 0x8e, 0x08, 0x02, 0xc5, 0x9b, 0x64, 0x9f, 0x4f, 0x85, - 0xfe, 0x75, 0xc5, 0xae, 0x5f, 0xf7, 0x73, 0x16, 0x8c, 0xa9, 0xaf, 0x3b, 0x81, 0xad, 0xbe, 0x60, - 0x6e, 0xf5, 0xf3, 0x5d, 0x17, 0x78, 0xce, 0x26, 0xff, 0x4a, 0x01, 0xce, 0x29, 0x1c, 0xca, 0xee, - 0xf3, 0x3f, 0x62, 0x55, 0x5d, 0x85, 0xb2, 0xaf, 0x04, 0x51, 0x96, 0x29, 0x01, 0x4a, 0xc4, 0x50, - 0x09, 0x0e, 0xe5, 0xda, 0xfc, 0x44, 0x5a, 0x34, 0xaa, 0x4b, 0x68, 0x85, 0x34, 0x76, 0x01, 0x8a, - 0x6d, 0xcf, 0x15, 0x77, 0xc6, 0xc7, 0xe4, 0x68, 0xdf, 0x59, 0xa9, 0x1c, 0x1e, 0xcc, 0x3e, 0x99, - 0xa7, 0x1d, 0xa0, 0x97, 0x55, 0x34, 0x77, 0x67, 0xa5, 0x82, 0x69, 0x65, 0x34, 0x0f, 0x13, 0x52, - 0x01, 0x72, 0x97, 0x72, 0x50, 0x81, 0x2f, 0xae, 0x16, 0x25, 0x66, 0xc5, 0x26, 0x18, 0xa7, 0xf1, - 0x51, 0x05, 0x26, 0x77, 0xda, 0x1b, 0xa4, 0x41, 0x62, 0xfe, 0xc1, 0x37, 0x09, 0x17, 0x42, 0x96, - 0x93, 0xc7, 0xd6, 0xcd, 0x14, 0x1c, 0x77, 0xd4, 0xb0, 0xff, 0x9c, 0x1d, 0xf1, 0x62, 0xf4, 0xaa, - 0x61, 0x40, 0x17, 0x16, 0xa5, 0xfe, 0xf5, 0x5c, 0xce, 0xfd, 0xac, 0x8a, 0x9b, 0x64, 0x7f, 0x3d, - 0xa0, 0xcc, 0x76, 0xf6, 0xaa, 0x30, 0xd6, 0xfc, 0x40, 0xd7, 0x35, 0xff, 0xf3, 0x05, 0x38, 0xa3, - 0x46, 0xc0, 0xe0, 0xeb, 0xfe, 0xa2, 0x8f, 0xc1, 0xf3, 0x30, 0xe2, 0x92, 0x4d, 0xa7, 0xdd, 0x88, - 0x95, 0x44, 0x7c, 0x90, 0x6b, 0x45, 0x2a, 0x49, 0x31, 0xd6, 0x71, 0x8e, 0x30, 0x6c, 0x3f, 0x31, - 0xc2, 0xee, 0xd6, 0xd8, 0xa1, 0x6b, 0x5c, 0xed, 0x1a, 0x2b, 0x77, 0xd7, 0x5c, 0x82, 0x41, 0xaf, - 0x49, 0x79, 0xad, 0x82, 0xc9, 0x42, 0xad, 0xd0, 0x42, 0xcc, 0x61, 0xe8, 0x23, 0x30, 0x5c, 0x0f, - 0x9a, 0x4d, 0xc7, 0x77, 0xd9, 0x95, 0x57, 0x5e, 0x18, 0xa1, 0xec, 0xd8, 0x22, 0x2f, 0xc2, 0x12, - 0x86, 0x9e, 0x80, 0x01, 0x27, 0xdc, 0xe2, 0x62, 0x89, 0xf2, 0x42, 0x89, 0xb6, 0x34, 0x1f, 0x6e, - 0x45, 0x98, 0x95, 0xd2, 0x57, 0xd5, 0x5e, 0x10, 0xee, 0x78, 0xfe, 0x56, 0xc5, 0x0b, 0xc5, 0x96, - 0x50, 0x77, 0xe1, 0x3d, 0x05, 0xc1, 0x1a, 0x16, 0x5a, 0x86, 0xc1, 0x56, 0x10, 0xc6, 0xd1, 0xf4, - 0x10, 0x1b, 0xee, 0x27, 0x73, 0x0e, 0x22, 0xfe, 0xb5, 0xd5, 0x20, 0x8c, 0x93, 0x0f, 0xa0, 0xff, - 0x22, 0xcc, 0xab, 0xa3, 0x5b, 0x30, 0x4c, 0xfc, 0xdd, 0xe5, 0x30, 0x68, 0x4e, 0x9f, 0xca, 0xa7, - 0xb4, 0xc4, 0x51, 0xf8, 0x32, 0x4b, 0xd8, 0x4e, 0x51, 0x8c, 0x25, 0x09, 0xf4, 0x4d, 0x50, 0x24, - 0xfe, 0xee, 0xf4, 0x30, 0xa3, 0x34, 0x93, 0x43, 0xe9, 0xae, 0x13, 0x26, 0x67, 0xfe, 0x92, 0xbf, - 0x8b, 0x69, 0x1d, 0xf4, 0x19, 0x28, 0xcb, 0x03, 0x23, 0x12, 0xf2, 0xb7, 0xcc, 0x05, 0x2b, 0x8f, - 0x19, 0x4c, 0xde, 0x69, 0x7b, 0x21, 0x69, 0x12, 0x3f, 0x8e, 0x92, 0x13, 0x52, 0x42, 0x23, 0x9c, - 0x50, 0x43, 0x9f, 0x91, 0x42, 0xdf, 0xd5, 0xa0, 0xed, 0xc7, 0xd1, 0x74, 0x99, 0x75, 0x2f, 0x53, - 0x1d, 0x77, 0x37, 0xc1, 0x4b, 0x4b, 0x85, 0x79, 0x65, 0x6c, 0x90, 0x42, 0x9f, 0x85, 0x31, 0xfe, - 0x9f, 0x2b, 0xb5, 0xa2, 0xe9, 0x33, 0x8c, 0xf6, 0xc5, 0x7c, 0xda, 0x1c, 0x71, 0xe1, 0x8c, 0x20, - 0x3e, 0xa6, 0x97, 0x46, 0xd8, 0xa4, 0x86, 0x30, 0x8c, 0x35, 0xbc, 0x5d, 0xe2, 0x93, 0x28, 0xaa, - 0x86, 0xc1, 0x06, 0x99, 0x06, 0x36, 0x30, 0xe7, 0xb2, 0x95, 0x60, 0xc1, 0x06, 0x59, 0x98, 0xa2, - 0x34, 0x6f, 0xe9, 0x75, 0xb0, 0x49, 0x02, 0xdd, 0x81, 0x71, 0xfa, 0x08, 0xf3, 0x12, 0xa2, 0x23, - 0xbd, 0x88, 0xb2, 0xa7, 0x12, 0x36, 0x2a, 0xe1, 0x14, 0x11, 0xf4, 0x3a, 0x94, 0x1b, 0xde, 0x26, - 0xa9, 0xef, 0xd7, 0x1b, 0x64, 0x7a, 0x94, 0x51, 0xcc, 0x3c, 0x03, 0x6e, 0x49, 0x24, 0xfe, 0x88, - 0x53, 0x7f, 0x71, 0x52, 0x1d, 0xdd, 0x85, 0xb3, 0x31, 0x09, 0x9b, 0x9e, 0xef, 0xd0, 0xbd, 0x2b, - 0x1e, 0x37, 0x4c, 0x95, 0x38, 0xc6, 0x36, 0xc7, 0x05, 0x31, 0x78, 0x67, 0xd7, 0x33, 0xb1, 0x70, - 0x4e, 0x6d, 0x74, 0x1f, 0xa6, 0x33, 0x20, 0x41, 0xc3, 0xab, 0xef, 0x4f, 0x9f, 0x66, 0x94, 0x3f, - 0x29, 0x28, 0x4f, 0xaf, 0xe7, 0xe0, 0x1d, 0x76, 0x81, 0xe1, 0x5c, 0xea, 0xe8, 0x36, 0x4c, 0xb0, - 0x03, 0xa3, 0xda, 0x6e, 0x34, 0x44, 0x83, 0xe3, 0xac, 0xc1, 0x8f, 0xc8, 0xeb, 0x73, 0xc5, 0x04, - 0x1f, 0x1e, 0xcc, 0x42, 0xf2, 0x0f, 0xa7, 0x6b, 0xa3, 0x0d, 0xa6, 0xb5, 0x6a, 0x87, 0x5e, 0xbc, - 0x4f, 0xb7, 0x39, 0xb9, 0x1f, 0x4f, 0x4f, 0x74, 0x95, 0x18, 0xe8, 0xa8, 0x4a, 0xb5, 0xa5, 0x17, - 0xe2, 0x34, 0x41, 0x7a, 0x02, 0x46, 0xb1, 0xeb, 0xf9, 0xd3, 0x93, 0xec, 0x60, 0x55, 0x07, 0x48, - 0x8d, 0x16, 0x62, 0x0e, 0x63, 0x1a, 0x2b, 0xfa, 0xe3, 0x36, 0xbd, 0x68, 0xa6, 0x18, 0x62, 0xa2, - 0xb1, 0x92, 0x00, 0x9c, 0xe0, 0x50, 0xde, 0x2f, 0x8e, 0xf7, 0xa7, 0x11, 0x43, 0x55, 0xe7, 0xc0, - 0xfa, 0xfa, 0x67, 0x30, 0x2d, 0xb7, 0x37, 0x60, 0x5c, 0x9d, 0x5b, 0x6c, 0x4c, 0xd0, 0x2c, 0x0c, - 0x32, 0x6e, 0x47, 0xc8, 0xb7, 0xca, 0xb4, 0x0b, 0x8c, 0x13, 0xc2, 0xbc, 0x9c, 0x75, 0xc1, 0x7b, - 0x97, 0x2c, 0xec, 0xc7, 0x84, 0xbf, 0xaa, 0x8b, 0x5a, 0x17, 0x24, 0x00, 0x27, 0x38, 0xf6, 0xff, - 0xe3, 0x5c, 0x63, 0x72, 0x38, 0xf6, 0x71, 0x1d, 0x3c, 0x0b, 0xa5, 0xed, 0x20, 0x8a, 0x29, 0x36, - 0x6b, 0x63, 0x30, 0xe1, 0x13, 0x6f, 0x88, 0x72, 0xac, 0x30, 0xd0, 0xab, 0x30, 0x56, 0xd7, 0x1b, - 0x10, 0x77, 0x99, 0xda, 0xf5, 0x46, 0xeb, 0xd8, 0xc4, 0x45, 0xaf, 0x40, 0x89, 0x59, 0x61, 0xd4, - 0x83, 0x86, 0x60, 0xb2, 0xe4, 0x85, 0x5c, 0xaa, 0x8a, 0xf2, 0x43, 0xed, 0x37, 0x56, 0xd8, 0xe8, - 0x32, 0x0c, 0xd1, 0x2e, 0xac, 0x54, 0xc5, 0x2d, 0xa2, 0x44, 0x35, 0x37, 0x58, 0x29, 0x16, 0x50, - 0xfb, 0x6f, 0x14, 0xb4, 0x51, 0xa6, 0x2f, 0x52, 0x82, 0xaa, 0x30, 0xbc, 0xe7, 0x78, 0xb1, 0xe7, - 0x6f, 0x09, 0x76, 0xe1, 0xe9, 0xae, 0x57, 0x0a, 0xab, 0x74, 0x8f, 0x57, 0xe0, 0x97, 0x9e, 0xf8, - 0x83, 0x25, 0x19, 0x4a, 0x31, 0x6c, 0xfb, 0x3e, 0xa5, 0x58, 0xe8, 0x97, 0x22, 0xe6, 0x15, 0x38, - 0x45, 0xf1, 0x07, 0x4b, 0x32, 0xe8, 0x2d, 0x00, 0xb9, 0xc3, 0x88, 0x2b, 0xac, 0x1f, 0x9e, 0xed, - 0x4d, 0x74, 0x5d, 0xd5, 0x59, 0x18, 0xa7, 0x57, 0x6a, 0xf2, 0x1f, 0x6b, 0xf4, 0xec, 0x98, 0xb1, - 0x55, 0x9d, 0x9d, 0x41, 0xdf, 0x4a, 0x97, 0xb8, 0x13, 0xc6, 0xc4, 0x9d, 0x8f, 0xc5, 0xe0, 0x7c, - 0xb4, 0xbf, 0x37, 0xc5, 0xba, 0xd7, 0x24, 0xfa, 0x76, 0x10, 0x44, 0x70, 0x42, 0xcf, 0xfe, 0xc5, - 0x22, 0x4c, 0xe7, 0x75, 0x97, 0x2e, 0x3a, 0x72, 0xdf, 0x8b, 0x17, 0x29, 0x37, 0x64, 0x99, 0x8b, - 0x6e, 0x49, 0x94, 0x63, 0x85, 0x41, 0x67, 0x3f, 0xf2, 0xb6, 0xe4, 0x93, 0x70, 0x30, 0x99, 0xfd, - 0x1a, 0x2b, 0xc5, 0x02, 0x4a, 0xf1, 0x42, 0xe2, 0x44, 0xc2, 0xbc, 0x46, 0x5b, 0x25, 0x98, 0x95, - 0x62, 0x01, 0xd5, 0xe5, 0x4d, 0x03, 0x3d, 0xe4, 0x4d, 0xc6, 0x10, 0x0d, 0x1e, 0xef, 0x10, 0xa1, - 0xcf, 0x01, 0x6c, 0x7a, 0xbe, 0x17, 0x6d, 0x33, 0xea, 0x43, 0x47, 0xa6, 0xae, 0x78, 0xa9, 0x65, - 0x45, 0x05, 0x6b, 0x14, 0xd1, 0x4b, 0x30, 0xa2, 0x36, 0xe0, 0x4a, 0x85, 0xe9, 0x1a, 0x35, 0xdb, - 0x8d, 0xe4, 0x34, 0xaa, 0x60, 0x1d, 0xcf, 0x7e, 0x3b, 0xbd, 0x5e, 0xc4, 0x0e, 0xd0, 0xc6, 0xd7, - 0xea, 0x77, 0x7c, 0x0b, 0xdd, 0xc7, 0xd7, 0xfe, 0xb5, 0x22, 0x4c, 0x18, 0x8d, 0xb5, 0xa3, 0x3e, - 0xce, 0xac, 0xeb, 0xf4, 0x00, 0x77, 0x62, 0x22, 0xf6, 0x9f, 0xdd, 0x7b, 0xab, 0xe8, 0x87, 0x3c, - 0xdd, 0x01, 0xbc, 0x3e, 0xfa, 0x1c, 0x94, 0x1b, 0x4e, 0xc4, 0x64, 0x57, 0x44, 0xec, 0xbb, 0x7e, - 0x88, 0x25, 0xef, 0x08, 0x27, 0x8a, 0xb5, 0x5b, 0x93, 0xd3, 0x4e, 0x48, 0xd2, 0x9b, 0x86, 0xb2, - 0x13, 0xd2, 0x7e, 0x4b, 0x75, 0x82, 0xf2, 0x1c, 0xfb, 0x98, 0xc3, 0xd0, 0x2b, 0x30, 0x1a, 0x12, - 0xb6, 0x2a, 0x16, 0x29, 0xf3, 0xc5, 0x96, 0xd9, 0x60, 0xc2, 0xa5, 0x61, 0x0d, 0x86, 0x0d, 0xcc, - 0x84, 0x95, 0x1f, 0xea, 0xc2, 0xca, 0x3f, 0x0d, 0xc3, 0xec, 0x87, 0x5a, 0x01, 0x6a, 0x36, 0x56, - 0x78, 0x31, 0x96, 0xf0, 0xf4, 0x82, 0x29, 0xf5, 0xb9, 0x60, 0x3e, 0x0a, 0xe3, 0x15, 0x87, 0x34, - 0x03, 0x7f, 0xc9, 0x77, 0x5b, 0x81, 0xe7, 0xc7, 0x68, 0x1a, 0x06, 0xd8, 0xed, 0xc0, 0xf7, 0xf6, - 0x00, 0xa5, 0x80, 0x07, 0x28, 0x63, 0x6e, 0x6f, 0xc1, 0x99, 0x4a, 0xb0, 0xe7, 0xef, 0x39, 0xa1, - 0x3b, 0x5f, 0x5d, 0xd1, 0xde, 0xb9, 0x6b, 0xf2, 0x9d, 0xc5, 0xed, 0xa1, 0x32, 0xcf, 0x54, 0xad, - 0x26, 0x67, 0x2f, 0x97, 0xbd, 0x06, 0xc9, 0x91, 0x46, 0xfc, 0xed, 0x82, 0xd1, 0x52, 0x82, 0xaf, - 0x14, 0x46, 0x56, 0xae, 0xc2, 0xe8, 0x0d, 0x28, 0x6d, 0x7a, 0xa4, 0xe1, 0x62, 0xb2, 0x29, 0x96, - 0xd8, 0x53, 0xf9, 0x26, 0x1e, 0xcb, 0x14, 0x53, 0x4a, 0x9f, 0xf8, 0x2b, 0x6d, 0x59, 0x54, 0xc6, - 0x8a, 0x0c, 0xda, 0x81, 0x49, 0xc9, 0xb8, 0x4b, 0xa8, 0x58, 0x70, 0x4f, 0x77, 0x7b, 0x0d, 0x98, - 0xc4, 0x4f, 0x3f, 0x38, 0x98, 0x9d, 0xc4, 0x29, 0x32, 0xb8, 0x83, 0x30, 0x7d, 0x96, 0x35, 0xe9, - 0xd1, 0x3a, 0xc0, 0x86, 0x9f, 0x3d, 0xcb, 0xd8, 0x0b, 0x93, 0x95, 0xda, 0x3f, 0x6a, 0xc1, 0x63, - 0x1d, 0x23, 0x23, 0x5e, 0xda, 0xc7, 0x3c, 0x0b, 0xe9, 0x97, 0x6f, 0xa1, 0xf7, 0xcb, 0xd7, 0xfe, - 0x59, 0x0b, 0x4e, 0x2f, 0x35, 0x5b, 0xf1, 0x7e, 0xc5, 0x33, 0xb5, 0x3b, 0x2f, 0xc3, 0x50, 0x93, - 0xb8, 0x5e, 0xbb, 0x29, 0x66, 0x6e, 0x56, 0x1e, 0x3f, 0xab, 0xac, 0xf4, 0xf0, 0x60, 0x76, 0xac, - 0x16, 0x07, 0xa1, 0xb3, 0x45, 0x78, 0x01, 0x16, 0xe8, 0xec, 0x10, 0xf7, 0xde, 0x25, 0xb7, 0xbc, - 0xa6, 0x27, 0x4d, 0x76, 0xba, 0xca, 0xce, 0xe6, 0xe4, 0x80, 0xce, 0xbd, 0xd1, 0x76, 0xfc, 0xd8, - 0x8b, 0xf7, 0x85, 0x62, 0x46, 0x12, 0xc1, 0x09, 0x3d, 0xfb, 0x6b, 0x16, 0x4c, 0xc8, 0x75, 0x3f, - 0xef, 0xba, 0x21, 0x89, 0x22, 0x34, 0x03, 0x05, 0xaf, 0x25, 0x7a, 0x09, 0xa2, 0x97, 0x85, 0x95, - 0x2a, 0x2e, 0x78, 0x2d, 0xc9, 0x6f, 0xb1, 0x13, 0xae, 0x68, 0xea, 0xa8, 0x6e, 0x88, 0x72, 0xac, - 0x30, 0xd0, 0x15, 0x28, 0xf9, 0x81, 0xcb, 0xcd, 0xa6, 0xf8, 0x5d, 0xc5, 0x16, 0xd8, 0x9a, 0x28, - 0xc3, 0x0a, 0x8a, 0xaa, 0x50, 0xe6, 0x16, 0x45, 0xc9, 0xa2, 0xed, 0xcb, 0x2e, 0x89, 0x7d, 0xd9, - 0xba, 0xac, 0x89, 0x13, 0x22, 0xf6, 0x0f, 0x58, 0x30, 0x2a, 0xbf, 0xac, 0x4f, 0x66, 0x92, 0x6e, - 0xad, 0x84, 0x91, 0x4c, 0xb6, 0x16, 0x65, 0x06, 0x19, 0xc4, 0xe0, 0x01, 0x8b, 0x47, 0xe1, 0x01, - 0xed, 0x1f, 0x29, 0xc0, 0xb8, 0xec, 0x4e, 0xad, 0xbd, 0x11, 0x91, 0x18, 0xad, 0x43, 0xd9, 0xe1, - 0x43, 0x4e, 0xe4, 0x8a, 0xbd, 0x94, 0xfd, 0x38, 0x37, 0xe6, 0x27, 0xb9, 0x96, 0xe7, 0x65, 0x6d, - 0x9c, 0x10, 0x42, 0x0d, 0x98, 0xf2, 0x83, 0x98, 0x1d, 0xd1, 0x0a, 0xde, 0x4d, 0x05, 0x92, 0xa6, - 0x7e, 0x4e, 0x50, 0x9f, 0x5a, 0x4b, 0x53, 0xc1, 0x9d, 0x84, 0xd1, 0x92, 0x14, 0x78, 0x14, 0xf3, - 0x5f, 0xd8, 0xfa, 0x2c, 0x64, 0xcb, 0x3b, 0xec, 0x5f, 0xb1, 0xa0, 0x2c, 0xd1, 0x4e, 0x42, 0xdb, - 0xb5, 0x0a, 0xc3, 0x11, 0x9b, 0x04, 0x39, 0x34, 0x76, 0xb7, 0x8e, 0xf3, 0xf9, 0x4a, 0x6e, 0x1e, - 0xfe, 0x3f, 0xc2, 0x92, 0x06, 0x93, 0x77, 0xab, 0xee, 0xbf, 0x4f, 0xe4, 0xdd, 0xaa, 0x3f, 0x39, - 0x37, 0xcc, 0xef, 0xb3, 0x3e, 0x6b, 0x02, 0x24, 0xca, 0x20, 0xb5, 0x42, 0xb2, 0xe9, 0xdd, 0x4f, - 0x33, 0x48, 0x55, 0x56, 0x8a, 0x05, 0x14, 0xbd, 0x05, 0xa3, 0x75, 0x29, 0xe8, 0x4c, 0xb6, 0xeb, - 0xe5, 0xae, 0x42, 0x77, 0xa5, 0x9f, 0xe1, 0x46, 0xda, 0x8b, 0x5a, 0x7d, 0x6c, 0x50, 0x33, 0xd5, - 0xed, 0xc5, 0x5e, 0xea, 0xf6, 0x84, 0x6e, 0xbe, 0xf2, 0xf9, 0xc7, 0x2c, 0x18, 0xe2, 0x02, 0xae, - 0xfe, 0xe4, 0x8b, 0x9a, 0xba, 0x2a, 0x19, 0xbb, 0xbb, 0xb4, 0x50, 0xa8, 0x9f, 0xd0, 0x2a, 0x94, - 0xd9, 0x0f, 0x26, 0xa0, 0x2b, 0xe6, 0x5b, 0xa7, 0xf3, 0x56, 0xf5, 0x0e, 0xde, 0x95, 0xd5, 0x70, - 0x42, 0xc1, 0xfe, 0xa1, 0x22, 0x3d, 0xaa, 0x12, 0x54, 0xe3, 0x06, 0xb7, 0x1e, 0xdd, 0x0d, 0x5e, - 0x78, 0x54, 0x37, 0xf8, 0x16, 0x4c, 0xd4, 0x35, 0xe5, 0x56, 0x32, 0x93, 0x57, 0xba, 0x2e, 0x12, - 0x4d, 0x0f, 0xc6, 0x65, 0x21, 0x8b, 0x26, 0x11, 0x9c, 0xa6, 0x8a, 0xbe, 0x15, 0x46, 0xf9, 0x3c, - 0x8b, 0x56, 0xb8, 0xc5, 0xc2, 0x47, 0xf2, 0xd7, 0x8b, 0xde, 0x04, 0x5b, 0x89, 0x35, 0xad, 0x3a, - 0x36, 0x88, 0xd9, 0x7f, 0x6c, 0x01, 0x5a, 0x6a, 0x6d, 0x93, 0x26, 0x09, 0x9d, 0x46, 0x22, 0xa3, - 0xfe, 0x6b, 0x16, 0x4c, 0x93, 0x8e, 0xe2, 0xc5, 0xa0, 0xd9, 0x14, 0x4f, 0x8b, 0x9c, 0xd7, 0xef, - 0x52, 0x4e, 0x1d, 0x65, 0xbe, 0x3f, 0x9d, 0x87, 0x81, 0x73, 0xdb, 0x43, 0xab, 0x70, 0x8a, 0x5f, - 0x79, 0x0a, 0xa0, 0xd9, 0x28, 0x3f, 0x2e, 0x08, 0x9f, 0x5a, 0xef, 0x44, 0xc1, 0x59, 0xf5, 0xec, - 0x2f, 0x8f, 0x40, 0x6e, 0x2f, 0x3e, 0x10, 0xce, 0x7f, 0x20, 0x9c, 0xff, 0x40, 0x38, 0xff, 0x81, - 0x70, 0xfe, 0x03, 0xe1, 0xfc, 0xfb, 0x4d, 0x38, 0xff, 0x87, 0x16, 0x9c, 0xea, 0x3c, 0xb5, 0x4f, - 0x82, 0x8f, 0x6e, 0xc3, 0xa9, 0xce, 0xab, 0xa9, 0xab, 0xf9, 0x58, 0x67, 0x3f, 0x93, 0x6b, 0x2a, - 0xe3, 0x1b, 0x70, 0x16, 0x7d, 0xfb, 0x17, 0x4b, 0x30, 0xb8, 0xb4, 0x4b, 0xfc, 0xf8, 0x04, 0x3e, - 0xb1, 0x0e, 0xe3, 0x9e, 0xbf, 0x1b, 0x34, 0x76, 0x89, 0xcb, 0xe1, 0x47, 0x79, 0x9e, 0x9e, 0x15, - 0xa4, 0xc7, 0x57, 0x0c, 0x12, 0x38, 0x45, 0xf2, 0x51, 0xc8, 0x7e, 0xaf, 0xc3, 0x10, 0x3f, 0xcc, - 0x85, 0xe0, 0x37, 0xf3, 0xec, 0x66, 0x83, 0x28, 0xae, 0xa8, 0x44, 0x2e, 0xcd, 0x2f, 0x0b, 0x51, - 0x1d, 0xbd, 0x0d, 0xe3, 0x9b, 0x5e, 0x18, 0xc5, 0xeb, 0x5e, 0x93, 0x44, 0xb1, 0xd3, 0x6c, 0x3d, - 0x84, 0xac, 0x57, 0x8d, 0xc3, 0xb2, 0x41, 0x09, 0xa7, 0x28, 0xa3, 0x2d, 0x18, 0x6b, 0x38, 0x7a, - 0x53, 0xc3, 0x47, 0x6e, 0x4a, 0xdd, 0x12, 0xb7, 0x74, 0x42, 0xd8, 0xa4, 0x4b, 0xf7, 0x69, 0x9d, - 0x89, 0x2b, 0x4b, 0xec, 0xad, 0xaf, 0xf6, 0x29, 0x97, 0x53, 0x72, 0x18, 0x65, 0x78, 0x98, 0x41, - 0x69, 0xd9, 0x64, 0x78, 0x34, 0xb3, 0xd1, 0xcf, 0x43, 0x99, 0xd0, 0x21, 0xa4, 0x84, 0xc5, 0x45, - 0x73, 0xb5, 0xbf, 0xbe, 0xae, 0x7a, 0xf5, 0x30, 0x30, 0xa5, 0xec, 0x4b, 0x92, 0x12, 0x4e, 0x88, - 0xa2, 0x45, 0x18, 0x8a, 0x48, 0xe8, 0x91, 0x48, 0x5c, 0x39, 0x5d, 0xa6, 0x91, 0xa1, 0x71, 0x5f, - 0x0c, 0xfe, 0x1b, 0x8b, 0xaa, 0x74, 0x79, 0x39, 0x4c, 0x4e, 0xc9, 0x6e, 0x19, 0x6d, 0x79, 0xcd, - 0xb3, 0x52, 0x2c, 0xa0, 0xe8, 0x75, 0x18, 0x0e, 0x49, 0x83, 0xa9, 0x71, 0xc6, 0xfa, 0x5f, 0xe4, - 0x5c, 0x2b, 0xc4, 0xeb, 0x61, 0x49, 0x00, 0xdd, 0x04, 0x14, 0x12, 0xca, 0x30, 0x79, 0xfe, 0x96, - 0x32, 0xb3, 0x14, 0x27, 0xb8, 0xda, 0xf1, 0x38, 0xc1, 0x90, 0x6e, 0x31, 0x38, 0xa3, 0x1a, 0xba, - 0x0e, 0x53, 0xaa, 0x74, 0xc5, 0x8f, 0x62, 0x87, 0x9e, 0x9c, 0x13, 0x8c, 0x96, 0x92, 0x57, 0xe0, - 0x34, 0x02, 0xee, 0xac, 0x63, 0xff, 0xb4, 0x05, 0x7c, 0x9c, 0x4f, 0xe0, 0x95, 0xfe, 0x9a, 0xf9, - 0x4a, 0x3f, 0x97, 0x3b, 0x73, 0x39, 0x2f, 0xf4, 0x07, 0x16, 0x8c, 0x68, 0x33, 0x9b, 0xac, 0x59, - 0xab, 0xcb, 0x9a, 0x6d, 0xc3, 0x24, 0x5d, 0xe9, 0xb7, 0x37, 0x22, 0x12, 0xee, 0x12, 0x97, 0x2d, - 0xcc, 0xc2, 0xc3, 0x2d, 0x4c, 0x65, 0xff, 0x75, 0x2b, 0x45, 0x10, 0x77, 0x34, 0x81, 0x5e, 0x96, - 0x3a, 0x8d, 0xa2, 0x61, 0x3e, 0xcd, 0xf5, 0x15, 0x87, 0x07, 0xb3, 0x93, 0xda, 0x87, 0xe8, 0x3a, - 0x0c, 0xfb, 0xf3, 0xf2, 0x1b, 0x95, 0x9d, 0x5d, 0x5d, 0x2d, 0x96, 0x94, 0x9d, 0x9d, 0x5a, 0x0e, - 0x38, 0xc1, 0xa1, 0x7b, 0x74, 0x3b, 0x88, 0xe2, 0xb4, 0x9d, 0xdd, 0x8d, 0x20, 0x8a, 0x31, 0x83, - 0xd8, 0x2f, 0x00, 0x2c, 0xdd, 0x27, 0x75, 0xbe, 0xd4, 0xf5, 0xd7, 0x87, 0x95, 0xff, 0xfa, 0xb0, - 0xff, 0xb3, 0x05, 0xe3, 0xcb, 0x8b, 0x86, 0x00, 0x77, 0x0e, 0x80, 0x3f, 0x99, 0xee, 0xdd, 0x5b, - 0x93, 0x5a, 0x6f, 0xae, 0xb8, 0x54, 0xa5, 0x58, 0xc3, 0x40, 0xe7, 0xa0, 0xd8, 0x68, 0xfb, 0x42, - 0x98, 0x38, 0x4c, 0x2f, 0xec, 0x5b, 0x6d, 0x1f, 0xd3, 0x32, 0xcd, 0x76, 0xbf, 0xd8, 0xb7, 0xed, - 0x7e, 0x4f, 0x1f, 0x7a, 0x34, 0x0b, 0x83, 0x7b, 0x7b, 0x9e, 0xcb, 0x3d, 0x15, 0x85, 0x46, 0xfe, - 0xde, 0xbd, 0x95, 0x4a, 0x84, 0x79, 0xb9, 0xfd, 0xa5, 0x22, 0xcc, 0x2c, 0x37, 0xc8, 0xfd, 0xf7, - 0xe8, 0xad, 0xd9, 0xaf, 0xe7, 0xc1, 0xd1, 0x24, 0x39, 0x47, 0xf5, 0x2e, 0xe9, 0x3d, 0x1e, 0x9b, - 0x30, 0xcc, 0xcd, 0xcc, 0xa4, 0xef, 0xe6, 0xab, 0x59, 0xad, 0xe7, 0x0f, 0xc8, 0x1c, 0x37, 0x57, - 0x13, 0xae, 0x67, 0xea, 0xa6, 0x15, 0xa5, 0x58, 0x12, 0x9f, 0xf9, 0x04, 0x8c, 0xea, 0x98, 0x47, - 0xf2, 0xf3, 0xfa, 0x2b, 0x45, 0x98, 0xa4, 0x3d, 0x78, 0xa4, 0x13, 0x71, 0xa7, 0x73, 0x22, 0x8e, - 0xdb, 0xd7, 0xa7, 0xf7, 0x6c, 0xbc, 0x95, 0x9e, 0x8d, 0xe7, 0xf3, 0x66, 0xe3, 0xa4, 0xe7, 0xe0, - 0xbb, 0x2c, 0x38, 0xb5, 0xdc, 0x08, 0xea, 0x3b, 0x29, 0x7f, 0x9c, 0x97, 0x60, 0x84, 0x9e, 0xe3, - 0x91, 0xe1, 0x2a, 0x6e, 0x04, 0x0f, 0x10, 0x20, 0xac, 0xe3, 0x69, 0xd5, 0xee, 0xdc, 0x59, 0xa9, - 0x64, 0xc5, 0x1c, 0x10, 0x20, 0xac, 0xe3, 0xd9, 0x5f, 0xb5, 0xe0, 0xfc, 0xf5, 0xc5, 0xa5, 0x64, - 0x29, 0x76, 0x84, 0x3d, 0xb8, 0x0c, 0x43, 0x2d, 0x57, 0xeb, 0x4a, 0x22, 0x9f, 0xad, 0xb0, 0x5e, - 0x08, 0xe8, 0xfb, 0x25, 0xa4, 0xc7, 0x4f, 0x59, 0x70, 0xea, 0xba, 0x17, 0xd3, 0x6b, 0x39, 0xed, - 0x80, 0x4f, 0xef, 0xe5, 0xc8, 0x8b, 0x83, 0x70, 0x3f, 0xed, 0x80, 0x8f, 0x15, 0x04, 0x6b, 0x58, - 0xbc, 0xe5, 0x5d, 0x8f, 0x19, 0x38, 0x17, 0x4c, 0xb5, 0x13, 0x16, 0xe5, 0x58, 0x61, 0xd0, 0x0f, - 0x73, 0xbd, 0x90, 0x09, 0xf9, 0xf6, 0xc5, 0x09, 0xab, 0x3e, 0xac, 0x22, 0x01, 0x38, 0xc1, 0xa1, - 0x0f, 0xa8, 0xd9, 0xeb, 0x8d, 0x76, 0x14, 0x93, 0x70, 0x33, 0xca, 0x39, 0x1d, 0x5f, 0x80, 0x32, - 0x91, 0x22, 0x75, 0xd1, 0x6b, 0xc5, 0x6a, 0x2a, 0x59, 0x3b, 0x8f, 0x03, 0xa0, 0xf0, 0xfa, 0xf0, - 0xee, 0x3b, 0x9a, 0x7b, 0xd6, 0x32, 0x20, 0xa2, 0xb7, 0xa5, 0x07, 0x46, 0x60, 0x1e, 0xd6, 0x4b, - 0x1d, 0x50, 0x9c, 0x51, 0xc3, 0xfe, 0x51, 0x0b, 0xce, 0xa8, 0x0f, 0x7e, 0xdf, 0x7d, 0xa6, 0xfd, - 0xe5, 0x02, 0x8c, 0xdd, 0x58, 0x5f, 0xaf, 0x5e, 0x27, 0xb1, 0xb8, 0xb6, 0x7b, 0x6b, 0xbd, 0xb1, - 0xa6, 0xbc, 0xeb, 0xf6, 0x0a, 0x6c, 0xc7, 0x5e, 0x63, 0x8e, 0xc7, 0xd7, 0x99, 0x5b, 0xf1, 0xe3, - 0xdb, 0x61, 0x2d, 0x0e, 0x3d, 0x7f, 0x2b, 0x53, 0xdd, 0x27, 0x99, 0x8b, 0x62, 0x1e, 0x73, 0x81, - 0x5e, 0x80, 0x21, 0x16, 0xe0, 0x47, 0x4e, 0xc2, 0xe3, 0xea, 0x11, 0xc5, 0x4a, 0x0f, 0x0f, 0x66, - 0xcb, 0x77, 0xf0, 0x0a, 0xff, 0x83, 0x05, 0x2a, 0xba, 0x03, 0x23, 0xdb, 0x71, 0xdc, 0xba, 0x41, - 0x1c, 0x97, 0xbe, 0x96, 0xf9, 0x71, 0x78, 0x21, 0xeb, 0x38, 0xa4, 0x83, 0xc0, 0xd1, 0x92, 0x13, - 0x24, 0x29, 0x8b, 0xb0, 0x4e, 0xc7, 0xae, 0x01, 0x24, 0xb0, 0x63, 0x52, 0x75, 0xd8, 0xbf, 0x67, - 0xc1, 0x30, 0x8f, 0xb5, 0x10, 0xa2, 0x4f, 0xc2, 0x00, 0xb9, 0x4f, 0xea, 0x82, 0x55, 0xce, 0xec, - 0x70, 0xc2, 0x69, 0x71, 0x91, 0x2d, 0xfd, 0x8f, 0x59, 0x2d, 0x74, 0x03, 0x86, 0x69, 0x6f, 0xaf, - 0xab, 0xc0, 0x13, 0x4f, 0xe6, 0x7d, 0xb1, 0x9a, 0x76, 0xce, 0x9c, 0x89, 0x22, 0x2c, 0xab, 0x33, - 0x65, 0x71, 0xbd, 0x55, 0xa3, 0x27, 0x76, 0xdc, 0x8d, 0xb1, 0x58, 0x5f, 0xac, 0x72, 0x24, 0x41, - 0x8d, 0x2b, 0x8b, 0x65, 0x21, 0x4e, 0x88, 0xd8, 0xeb, 0x50, 0xa6, 0x93, 0x3a, 0xdf, 0xf0, 0x9c, - 0xee, 0xfa, 0xef, 0x67, 0xa0, 0x2c, 0xb5, 0xdb, 0x91, 0xf0, 0xb1, 0x66, 0x54, 0xa5, 0xf2, 0x3b, - 0xc2, 0x09, 0xdc, 0xde, 0x84, 0xd3, 0xcc, 0x08, 0xd1, 0x89, 0xb7, 0x8d, 0x3d, 0xd6, 0x7b, 0x31, - 0x3f, 0x2b, 0x5e, 0x9e, 0x7c, 0x66, 0xa6, 0x35, 0x37, 0xc6, 0x51, 0x49, 0x31, 0x79, 0x85, 0xda, - 0x7f, 0x30, 0x00, 0x8f, 0xaf, 0xd4, 0xf2, 0xc3, 0x70, 0xbc, 0x02, 0xa3, 0x9c, 0x2f, 0xa5, 0x4b, - 0xdb, 0x69, 0x88, 0x76, 0x95, 0xac, 0x76, 0x5d, 0x83, 0x61, 0x03, 0x13, 0x9d, 0x87, 0xa2, 0xf7, - 0x8e, 0x9f, 0xf6, 0x08, 0x5a, 0x79, 0x63, 0x0d, 0xd3, 0x72, 0x0a, 0xa6, 0x2c, 0x2e, 0xbf, 0x3b, - 0x14, 0x58, 0xb1, 0xb9, 0xaf, 0xc1, 0xb8, 0x17, 0xd5, 0x23, 0x6f, 0xc5, 0xa7, 0xe7, 0x8c, 0x76, - 0x52, 0x29, 0xa9, 0x08, 0xed, 0xb4, 0x82, 0xe2, 0x14, 0xb6, 0x76, 0x91, 0x0d, 0xf6, 0xcd, 0x26, - 0xf7, 0x74, 0x3a, 0xa6, 0x2f, 0x80, 0x16, 0xfb, 0xba, 0x88, 0x09, 0xdd, 0xc5, 0x0b, 0x80, 0x7f, - 0x70, 0x84, 0x25, 0x8c, 0x3e, 0x39, 0xeb, 0xdb, 0x4e, 0x6b, 0xbe, 0x1d, 0x6f, 0x57, 0xbc, 0xa8, - 0x1e, 0xec, 0x92, 0x70, 0x9f, 0x49, 0x0b, 0x4a, 0xc9, 0x93, 0x53, 0x01, 0x16, 0x6f, 0xcc, 0x57, - 0x29, 0x26, 0xee, 0xac, 0x83, 0xe6, 0x61, 0x42, 0x16, 0xd6, 0x48, 0xc4, 0xae, 0xb0, 0x11, 0x46, - 0x46, 0xf9, 0xe8, 0x88, 0x62, 0x45, 0x24, 0x8d, 0x6f, 0x72, 0xd2, 0x70, 0x1c, 0x9c, 0xf4, 0xcb, - 0x30, 0xe6, 0xf9, 0x5e, 0xec, 0x39, 0x71, 0xc0, 0x35, 0x46, 0x5c, 0x30, 0xc0, 0x44, 0xe1, 0x2b, - 0x3a, 0x00, 0x9b, 0x78, 0xf6, 0xff, 0x18, 0x80, 0x29, 0x36, 0x6d, 0x1f, 0xac, 0xb0, 0x6f, 0xa4, - 0x15, 0x76, 0xa7, 0x73, 0x85, 0x1d, 0xc7, 0x13, 0xe1, 0xa1, 0x97, 0xd9, 0xdb, 0x50, 0x56, 0x6e, - 0x49, 0xd2, 0x2f, 0xd1, 0xca, 0xf1, 0x4b, 0xec, 0xcd, 0x7d, 0x48, 0x8b, 0xb2, 0x62, 0xa6, 0x45, - 0xd9, 0xdf, 0xb5, 0x20, 0xd1, 0xa9, 0xa0, 0x1b, 0x50, 0x6e, 0x05, 0xcc, 0x02, 0x32, 0x94, 0x66, - 0xc5, 0x8f, 0x67, 0x5e, 0x54, 0xfc, 0x52, 0xe4, 0x1f, 0x5f, 0x95, 0x35, 0x70, 0x52, 0x19, 0x2d, - 0xc0, 0x70, 0x2b, 0x24, 0xb5, 0x98, 0x45, 0xe3, 0xe8, 0x49, 0x87, 0xaf, 0x11, 0x8e, 0x8f, 0x65, - 0x45, 0xfb, 0xe7, 0x2d, 0x00, 0x6e, 0xb4, 0xe5, 0xf8, 0x5b, 0xe4, 0x04, 0xc4, 0xdd, 0x15, 0x18, - 0x88, 0x5a, 0xa4, 0xde, 0xcd, 0x36, 0x35, 0xe9, 0x4f, 0xad, 0x45, 0xea, 0xc9, 0x80, 0xd3, 0x7f, - 0x98, 0xd5, 0xb6, 0xbf, 0x1b, 0x60, 0x3c, 0x41, 0x5b, 0x89, 0x49, 0x13, 0x3d, 0x67, 0x78, 0xe7, - 0x9f, 0x4b, 0x79, 0xe7, 0x97, 0x19, 0xb6, 0x26, 0x59, 0x7d, 0x1b, 0x8a, 0x4d, 0xe7, 0xbe, 0x10, - 0x9d, 0x3d, 0xd3, 0xbd, 0x1b, 0x94, 0xfe, 0xdc, 0xaa, 0x73, 0x9f, 0x3f, 0x12, 0x9f, 0x91, 0x0b, - 0x64, 0xd5, 0xb9, 0x7f, 0xc8, 0x2d, 0x50, 0xd9, 0x21, 0x75, 0xcb, 0x8b, 0xe2, 0x2f, 0xfc, 0xf7, - 0xe4, 0x3f, 0x5b, 0x76, 0xb4, 0x11, 0xd6, 0x96, 0xe7, 0x0b, 0x13, 0xa6, 0xbe, 0xda, 0xf2, 0xfc, - 0x74, 0x5b, 0x9e, 0xdf, 0x47, 0x5b, 0x9e, 0x8f, 0xde, 0x85, 0x61, 0x61, 0x2e, 0x28, 0xa2, 0xe1, - 0x5c, 0xed, 0xa3, 0x3d, 0x61, 0x6d, 0xc8, 0xdb, 0xbc, 0x2a, 0x1f, 0xc1, 0xa2, 0xb4, 0x67, 0xbb, - 0xb2, 0x41, 0xf4, 0xb7, 0x2c, 0x18, 0x17, 0xbf, 0x31, 0x79, 0xa7, 0x4d, 0xa2, 0x58, 0xf0, 0x9e, - 0x1f, 0xef, 0xbf, 0x0f, 0xa2, 0x22, 0xef, 0xca, 0xc7, 0xe5, 0x31, 0x6b, 0x02, 0x7b, 0xf6, 0x28, - 0xd5, 0x0b, 0xf4, 0x8f, 0x2d, 0x38, 0xdd, 0x74, 0xee, 0xf3, 0x16, 0x79, 0x19, 0x76, 0x62, 0x2f, - 0x10, 0x9a, 0xfa, 0x4f, 0xf6, 0x37, 0xfd, 0x1d, 0xd5, 0x79, 0x27, 0xa5, 0x7e, 0xf2, 0x74, 0x16, - 0x4a, 0xcf, 0xae, 0x66, 0xf6, 0x6b, 0x66, 0x13, 0x4a, 0x72, 0xbd, 0x65, 0x88, 0x1a, 0x2a, 0x3a, - 0x63, 0x7d, 0x64, 0x6b, 0x4d, 0xdd, 0x45, 0x9e, 0xb6, 0x23, 0xd6, 0xda, 0x23, 0x6d, 0xe7, 0x6d, - 0x18, 0xd5, 0xd7, 0xd8, 0x23, 0x6d, 0xeb, 0x1d, 0x38, 0x95, 0xb1, 0x96, 0x1e, 0x69, 0x93, 0x7b, - 0x70, 0x2e, 0x77, 0x7d, 0x3c, 0xca, 0x86, 0xed, 0x2f, 0x5b, 0xfa, 0x39, 0x78, 0x02, 0x3a, 0x87, - 0x45, 0x53, 0xe7, 0x70, 0xa1, 0xfb, 0xce, 0xc9, 0x51, 0x3c, 0xbc, 0xa5, 0x77, 0x9a, 0x9e, 0xea, - 0xe8, 0x75, 0x18, 0x6a, 0xd0, 0x12, 0x69, 0xa7, 0x6a, 0xf7, 0xde, 0x91, 0x09, 0x2f, 0xc5, 0xca, - 0x23, 0x2c, 0x28, 0xd8, 0xbf, 0x64, 0xc1, 0xc0, 0x09, 0x8c, 0x04, 0x36, 0x47, 0xe2, 0xb9, 0x5c, - 0xd2, 0x22, 0x50, 0xef, 0x1c, 0x76, 0xf6, 0x96, 0xee, 0xc7, 0xc4, 0x8f, 0xd8, 0x53, 0x31, 0x73, - 0x60, 0xbe, 0x0d, 0x4e, 0xdd, 0x0a, 0x1c, 0x77, 0xc1, 0x69, 0x38, 0x7e, 0x9d, 0x84, 0x2b, 0xfe, - 0xd6, 0x91, 0x0c, 0xa6, 0x0b, 0xbd, 0x0c, 0xa6, 0xed, 0x6d, 0x40, 0x7a, 0x03, 0xc2, 0xa5, 0x04, - 0xc3, 0xb0, 0xc7, 0x9b, 0x12, 0xc3, 0xff, 0x54, 0x36, 0x6b, 0xd6, 0xd1, 0x33, 0xcd, 0x59, 0x82, - 0x17, 0x60, 0x49, 0xc8, 0x7e, 0x05, 0x32, 0xdd, 0xc8, 0x7b, 0x8b, 0x0d, 0xec, 0xcf, 0xc0, 0x14, - 0xab, 0x79, 0xc4, 0x27, 0xad, 0x9d, 0x92, 0x4a, 0x66, 0xc4, 0x8c, 0xb3, 0xbf, 0x68, 0xc1, 0xc4, - 0x5a, 0x2a, 0x94, 0xd6, 0x65, 0xa6, 0x00, 0xcd, 0x10, 0x86, 0xd7, 0x58, 0x29, 0x16, 0xd0, 0x63, - 0x97, 0x41, 0xfd, 0xb9, 0x05, 0x49, 0x64, 0x87, 0x13, 0x60, 0xbc, 0x16, 0x0d, 0xc6, 0x2b, 0x53, - 0x36, 0xa2, 0xba, 0x93, 0xc7, 0x77, 0xa1, 0x9b, 0x2a, 0x8c, 0x51, 0x17, 0xb1, 0x48, 0x42, 0x86, - 0x07, 0xbd, 0x19, 0x37, 0x63, 0x1d, 0xc9, 0xc0, 0x46, 0xcc, 0xaa, 0x59, 0xe1, 0xbe, 0x4f, 0xac, - 0x9a, 0x55, 0x7f, 0x72, 0x76, 0x68, 0x55, 0xeb, 0x32, 0x3b, 0xb9, 0xbe, 0x99, 0x79, 0xa9, 0x39, - 0x0d, 0xef, 0x5d, 0xa2, 0x62, 0xb1, 0xcd, 0x0a, 0xaf, 0x33, 0x51, 0x7a, 0x78, 0x30, 0x3b, 0xa6, - 0xfe, 0xf1, 0xd8, 0xaf, 0x49, 0x15, 0xfb, 0x06, 0x4c, 0xa4, 0x06, 0x0c, 0xbd, 0x04, 0x83, 0xad, - 0x6d, 0x27, 0x22, 0x29, 0x4f, 0x8e, 0xc1, 0x2a, 0x2d, 0x3c, 0x3c, 0x98, 0x1d, 0x57, 0x15, 0x58, - 0x09, 0xe6, 0xd8, 0xf6, 0x1f, 0x5b, 0x30, 0xb0, 0x16, 0xb8, 0x27, 0xb1, 0x98, 0x5e, 0x33, 0x16, - 0xd3, 0x13, 0x79, 0x91, 0xb3, 0x73, 0xd7, 0xd1, 0x72, 0x6a, 0x1d, 0x5d, 0xc8, 0xa5, 0xd0, 0x7d, - 0x09, 0x35, 0x61, 0x84, 0xc5, 0xe3, 0x16, 0x9e, 0x25, 0x2f, 0x18, 0x6f, 0x80, 0xd9, 0xd4, 0x1b, - 0x60, 0x42, 0x43, 0xd5, 0x5e, 0x02, 0x4f, 0xc3, 0xb0, 0xf0, 0x6e, 0x48, 0xfb, 0xe3, 0x09, 0x5c, - 0x2c, 0xe1, 0xf6, 0x8f, 0x15, 0xc1, 0x88, 0xff, 0x8d, 0x7e, 0xc5, 0x82, 0xb9, 0x90, 0x5b, 0x3d, - 0xba, 0x95, 0x76, 0xe8, 0xf9, 0x5b, 0xb5, 0xfa, 0x36, 0x71, 0xdb, 0x0d, 0xcf, 0xdf, 0x5a, 0xd9, - 0xf2, 0x03, 0x55, 0xbc, 0x74, 0x9f, 0xd4, 0xdb, 0x4c, 0x11, 0xd2, 0x23, 0xd8, 0xb8, 0xb2, 0x1e, - 0xbe, 0xf6, 0xe0, 0x60, 0x76, 0x0e, 0x1f, 0x89, 0x36, 0x3e, 0x62, 0x5f, 0xd0, 0x57, 0x2d, 0xb8, - 0xca, 0xc3, 0x62, 0xf7, 0xdf, 0xff, 0x2e, 0x2f, 0xa6, 0xaa, 0x24, 0x95, 0x10, 0x59, 0x27, 0x61, - 0x73, 0xe1, 0x65, 0x31, 0xa0, 0x57, 0xab, 0x47, 0x6b, 0x0b, 0x1f, 0xb5, 0x73, 0xf6, 0xbf, 0x2e, - 0xc2, 0x98, 0x88, 0xad, 0x23, 0x82, 0xb6, 0xbd, 0x64, 0x2c, 0x89, 0x27, 0x53, 0x4b, 0x62, 0xca, - 0x40, 0x3e, 0x9e, 0x78, 0x6d, 0x11, 0x4c, 0x35, 0x9c, 0x28, 0xbe, 0x41, 0x9c, 0x30, 0xde, 0x20, - 0x0e, 0xb7, 0xdd, 0x29, 0x1e, 0xd9, 0xce, 0x48, 0x89, 0x68, 0x6e, 0xa5, 0x89, 0xe1, 0x4e, 0xfa, - 0x68, 0x17, 0x10, 0x33, 0x40, 0x0a, 0x1d, 0x3f, 0xe2, 0xdf, 0xe2, 0x09, 0x9d, 0xc1, 0xd1, 0x5a, - 0x9d, 0x11, 0xad, 0xa2, 0x5b, 0x1d, 0xd4, 0x70, 0x46, 0x0b, 0x9a, 0x61, 0xd9, 0x60, 0xbf, 0x86, - 0x65, 0x43, 0x3d, 0x9c, 0x5e, 0x7d, 0x98, 0xec, 0x08, 0x8f, 0xf4, 0x26, 0x94, 0x95, 0x69, 0xbe, - 0x38, 0x74, 0xba, 0x47, 0x19, 0x4b, 0x53, 0xe0, 0x62, 0x94, 0xc4, 0x2d, 0x24, 0x21, 0x67, 0xff, - 0x93, 0x82, 0xd1, 0x20, 0x9f, 0xc4, 0x35, 0x28, 0x39, 0x51, 0xe4, 0x6d, 0xf9, 0xc4, 0x15, 0x3b, - 0xf6, 0xc3, 0x79, 0x3b, 0xd6, 0x68, 0x86, 0xb9, 0x47, 0xcc, 0x8b, 0x9a, 0x58, 0xd1, 0x40, 0x37, - 0xb8, 0x85, 0xd4, 0xae, 0xe4, 0xf9, 0xfb, 0xa3, 0x06, 0xd2, 0x86, 0x6a, 0x97, 0x60, 0x51, 0x1f, - 0x7d, 0x96, 0x9b, 0xb0, 0xdd, 0xf4, 0x83, 0x3d, 0xff, 0x7a, 0x10, 0x48, 0x87, 0xf8, 0xfe, 0x08, - 0x4e, 0x49, 0xc3, 0x35, 0x55, 0x1d, 0x9b, 0xd4, 0xfa, 0x0b, 0x21, 0xf8, 0xed, 0x70, 0x8a, 0x92, - 0x36, 0xdd, 0x5a, 0x23, 0x44, 0x60, 0x42, 0x04, 0x6e, 0x92, 0x65, 0x62, 0xec, 0x32, 0xd9, 0x79, - 0xb3, 0x76, 0x22, 0x4b, 0xbc, 0x69, 0x92, 0xc0, 0x69, 0x9a, 0xf6, 0x4f, 0x5a, 0xc0, 0x5c, 0xfc, - 0x4e, 0x80, 0x65, 0xf8, 0x94, 0xc9, 0x32, 0x4c, 0xe7, 0x0d, 0x72, 0x0e, 0xb7, 0xf0, 0x22, 0x5f, - 0x59, 0xd5, 0x30, 0xb8, 0xbf, 0x2f, 0xcc, 0x07, 0x7a, 0x73, 0xb2, 0xf6, 0xff, 0xb5, 0xf8, 0x21, - 0xa6, 0x0c, 0xe7, 0xd1, 0x77, 0x40, 0xa9, 0xee, 0xb4, 0x9c, 0x3a, 0x4f, 0x56, 0x91, 0x2b, 0xd5, - 0x31, 0x2a, 0xcd, 0x2d, 0x8a, 0x1a, 0x5c, 0x4a, 0x21, 0x03, 0x80, 0x95, 0x64, 0x71, 0x4f, 0xc9, - 0x84, 0x6a, 0x72, 0x66, 0x07, 0xc6, 0x0c, 0x62, 0x8f, 0xf4, 0x49, 0xfb, 0x1d, 0xfc, 0x8a, 0x55, - 0x01, 0xeb, 0x9a, 0x30, 0xe5, 0x6b, 0xff, 0xe9, 0x85, 0x22, 0x9f, 0x29, 0x1f, 0xee, 0x75, 0x89, - 0xb2, 0xdb, 0x47, 0x73, 0x38, 0x4c, 0x91, 0xc1, 0x9d, 0x94, 0xed, 0x1f, 0xb7, 0xe0, 0x31, 0x1d, - 0x51, 0xf3, 0x69, 0xe8, 0x25, 0x27, 0xae, 0x40, 0x29, 0x68, 0x91, 0xd0, 0x89, 0x83, 0x50, 0xdc, - 0x1a, 0x57, 0xe4, 0xa0, 0xdf, 0x16, 0xe5, 0x87, 0x22, 0xd4, 0xb3, 0xa4, 0x2e, 0xcb, 0xb1, 0xaa, - 0x49, 0xdf, 0x31, 0x6c, 0x30, 0x22, 0xe1, 0xbd, 0xc2, 0xce, 0x00, 0xa6, 0x32, 0x8d, 0xb0, 0x80, - 0xd8, 0x7f, 0x60, 0xf1, 0x85, 0xa5, 0x77, 0x1d, 0xbd, 0x03, 0x93, 0x4d, 0x27, 0xae, 0x6f, 0x2f, - 0xdd, 0x6f, 0x85, 0x5c, 0xea, 0x2e, 0xc7, 0xe9, 0x99, 0x5e, 0xe3, 0xa4, 0x7d, 0x64, 0x62, 0x95, - 0xb7, 0x9a, 0x22, 0x86, 0x3b, 0xc8, 0xa3, 0x0d, 0x18, 0x61, 0x65, 0xcc, 0x31, 0x2b, 0xea, 0xc6, - 0x1a, 0xe4, 0xb5, 0xa6, 0xb4, 0xce, 0xab, 0x09, 0x1d, 0xac, 0x13, 0xb5, 0x7f, 0xb6, 0xc8, 0x77, - 0x3b, 0xe3, 0xb6, 0x9f, 0x86, 0xe1, 0x56, 0xe0, 0x2e, 0xae, 0x54, 0xb0, 0x98, 0x05, 0x75, 0x8d, - 0x54, 0x79, 0x31, 0x96, 0x70, 0x74, 0x05, 0x4a, 0xe2, 0xa7, 0xd4, 0x92, 0xb0, 0xb3, 0x59, 0xe0, - 0x45, 0x58, 0x41, 0xd1, 0x35, 0x80, 0x56, 0x18, 0xec, 0x7a, 0x2e, 0x73, 0xeb, 0x2f, 0x9a, 0x06, - 0x23, 0x55, 0x05, 0xc1, 0x1a, 0x16, 0x7a, 0x15, 0xc6, 0xda, 0x7e, 0xc4, 0xd9, 0x11, 0x67, 0x43, - 0x44, 0x45, 0x2e, 0x25, 0xa6, 0x0c, 0x77, 0x74, 0x20, 0x36, 0x71, 0xd1, 0x3c, 0x0c, 0xc5, 0x0e, - 0x33, 0x80, 0x18, 0xcc, 0xb7, 0xdc, 0x5c, 0xa7, 0x18, 0x7a, 0x5e, 0x04, 0x5a, 0x01, 0x8b, 0x8a, - 0xe8, 0x4d, 0xe9, 0x23, 0xc9, 0x0f, 0x76, 0x61, 0x32, 0xdd, 0xdf, 0x25, 0xa0, 0x79, 0x48, 0x0a, - 0x53, 0x6c, 0x83, 0x16, 0x7a, 0x15, 0x80, 0xdc, 0x8f, 0x49, 0xe8, 0x3b, 0x0d, 0x65, 0x5f, 0xa4, - 0x2c, 0x6a, 0x2b, 0xc1, 0x5a, 0x10, 0xdf, 0x89, 0xc8, 0xb7, 0x2d, 0x29, 0x14, 0xac, 0xa1, 0xdb, - 0x5f, 0x2d, 0x03, 0x24, 0x8c, 0x3b, 0x7a, 0xb7, 0xe3, 0xe4, 0x7a, 0xb6, 0x3b, 0xab, 0x7f, 0x7c, - 0xc7, 0x16, 0xfa, 0x1e, 0x0b, 0x46, 0x9c, 0x46, 0x23, 0xa8, 0x3b, 0x31, 0x9b, 0xa2, 0x42, 0xf7, - 0x93, 0x53, 0xb4, 0x3f, 0x9f, 0xd4, 0xe0, 0x5d, 0x78, 0x41, 0x2e, 0x51, 0x0d, 0xd2, 0xb3, 0x17, - 0x7a, 0xc3, 0xe8, 0x63, 0xf2, 0x3d, 0xc7, 0xd7, 0xd6, 0x4c, 0xfa, 0x3d, 0x57, 0x66, 0x97, 0x84, - 0xf6, 0x94, 0x43, 0x77, 0x8c, 0x68, 0xb9, 0x03, 0xf9, 0x5e, 0x60, 0x06, 0xff, 0xda, 0x2b, 0x50, - 0x2e, 0xaa, 0xea, 0x1e, 0xe1, 0x83, 0xf9, 0x2e, 0x57, 0xda, 0x43, 0xa9, 0x87, 0x37, 0xf8, 0xdb, - 0x30, 0xe1, 0x9a, 0x5c, 0x80, 0x58, 0x8a, 0x4f, 0xe5, 0xd1, 0x4d, 0x31, 0x0d, 0xc9, 0xbd, 0x9f, - 0x02, 0xe0, 0x34, 0x61, 0x54, 0xe5, 0xde, 0xfe, 0x2b, 0xfe, 0x66, 0x20, 0xec, 0xf6, 0xed, 0xdc, - 0xb9, 0xdc, 0x8f, 0x62, 0xd2, 0xa4, 0x98, 0xc9, 0xf5, 0xbe, 0x26, 0xea, 0x62, 0x45, 0x05, 0xbd, - 0x0e, 0x43, 0xcc, 0x89, 0x27, 0x9a, 0x2e, 0xe5, 0x8b, 0x1d, 0xcd, 0xb8, 0x54, 0xc9, 0x8e, 0x64, - 0x7f, 0x23, 0x2c, 0x28, 0xa0, 0x1b, 0xd2, 0xa3, 0x2d, 0x5a, 0xf1, 0xef, 0x44, 0x84, 0x79, 0xb4, - 0x95, 0x17, 0x3e, 0x9c, 0x38, 0xab, 0xf1, 0xf2, 0xcc, 0xf4, 0x49, 0x46, 0x4d, 0xca, 0x46, 0x89, - 0xff, 0x32, 0x2b, 0xd3, 0x34, 0xe4, 0x77, 0xcf, 0xcc, 0xdc, 0x94, 0x0c, 0xe7, 0x5d, 0x93, 0x04, - 0x4e, 0xd3, 0xa4, 0x2c, 0x29, 0xdf, 0xf6, 0xc2, 0xf2, 0xbf, 0xd7, 0xe1, 0xc1, 0x5f, 0xe2, 0xec, - 0x3a, 0xe2, 0x25, 0x58, 0xd4, 0x3f, 0x51, 0xfe, 0x60, 0xc6, 0x87, 0xc9, 0xf4, 0x16, 0x7d, 0xa4, - 0xfc, 0xc8, 0xef, 0x0d, 0xc0, 0xb8, 0xb9, 0xa4, 0xd0, 0x55, 0x28, 0x0b, 0x22, 0x2a, 0x92, 0xba, - 0xda, 0x25, 0xab, 0x12, 0x80, 0x13, 0x1c, 0x16, 0x40, 0x9f, 0x55, 0xd7, 0x2c, 0x36, 0x93, 0x00, - 0xfa, 0x0a, 0x82, 0x35, 0x2c, 0xfa, 0xb2, 0xda, 0x08, 0x82, 0x58, 0xdd, 0x48, 0x6a, 0xdd, 0x2d, - 0xb0, 0x52, 0x2c, 0xa0, 0xf4, 0x26, 0xda, 0x21, 0xa1, 0x4f, 0x1a, 0x66, 0x80, 0x56, 0x75, 0x13, - 0xdd, 0xd4, 0x81, 0xd8, 0xc4, 0xa5, 0xf7, 0x69, 0x10, 0xb1, 0x85, 0x2c, 0xde, 0x6f, 0x89, 0x05, - 0x6c, 0x8d, 0x3b, 0xd5, 0x4a, 0x38, 0xfa, 0x0c, 0x3c, 0xa6, 0xa2, 0xda, 0x60, 0x2e, 0xd2, 0x96, - 0x2d, 0x0e, 0x19, 0xe2, 0x96, 0xc7, 0x16, 0xb3, 0xd1, 0x70, 0x5e, 0x7d, 0xf4, 0x1a, 0x8c, 0x0b, - 0x1e, 0x5f, 0x52, 0x1c, 0x36, 0xad, 0x2c, 0x6e, 0x1a, 0x50, 0x9c, 0xc2, 0x96, 0x21, 0x66, 0x19, - 0x9b, 0x2d, 0x29, 0x94, 0x3a, 0x43, 0xcc, 0xea, 0x70, 0xdc, 0x51, 0x03, 0xcd, 0xc3, 0x04, 0x67, - 0xc2, 0x3c, 0x7f, 0x8b, 0xcf, 0x89, 0x70, 0xcc, 0x51, 0x5b, 0xea, 0xb6, 0x09, 0xc6, 0x69, 0x7c, - 0xf4, 0x0a, 0x8c, 0x3a, 0x61, 0x7d, 0xdb, 0x8b, 0x49, 0x3d, 0x6e, 0x87, 0xdc, 0x63, 0x47, 0x33, - 0x53, 0x99, 0xd7, 0x60, 0xd8, 0xc0, 0xb4, 0xdf, 0x85, 0x53, 0x19, 0xde, 0xf6, 0x74, 0xe1, 0x38, - 0x2d, 0x4f, 0x7e, 0x53, 0xca, 0x96, 0x75, 0xbe, 0xba, 0x22, 0xbf, 0x46, 0xc3, 0xa2, 0xab, 0x93, - 0x79, 0xe5, 0x6b, 0x49, 0xd8, 0xd4, 0xea, 0x5c, 0x96, 0x00, 0x9c, 0xe0, 0xd8, 0xff, 0xbb, 0x00, - 0x13, 0x19, 0x62, 0x7a, 0x96, 0x08, 0x2c, 0xf5, 0x4a, 0x49, 0xf2, 0x7e, 0x99, 0x11, 0x8b, 0x0b, - 0x47, 0x88, 0x58, 0x5c, 0xec, 0x15, 0xb1, 0x78, 0xe0, 0xbd, 0x44, 0x2c, 0x36, 0x47, 0x6c, 0xb0, - 0xaf, 0x11, 0xcb, 0x88, 0x72, 0x3c, 0x74, 0xc4, 0x28, 0xc7, 0xc6, 0xa0, 0x0f, 0xf7, 0x31, 0xe8, - 0x3f, 0x54, 0x80, 0xc9, 0xb4, 0x39, 0xdd, 0x09, 0x08, 0x6e, 0x5f, 0x37, 0x04, 0xb7, 0xd9, 0x69, - 0xf5, 0xd2, 0x46, 0x7e, 0x79, 0x42, 0x5c, 0x9c, 0x12, 0xe2, 0x7e, 0xb4, 0x2f, 0x6a, 0xdd, 0x05, - 0xba, 0x7f, 0xbf, 0x00, 0x67, 0xd2, 0x55, 0x16, 0x1b, 0x8e, 0xd7, 0x3c, 0x81, 0xb1, 0xb9, 0x6d, - 0x8c, 0xcd, 0x73, 0xfd, 0x7c, 0x0d, 0xeb, 0x5a, 0xee, 0x00, 0xdd, 0x4b, 0x0d, 0xd0, 0xd5, 0xfe, - 0x49, 0x76, 0x1f, 0xa5, 0xaf, 0x15, 0xe1, 0x42, 0x66, 0xbd, 0x44, 0xee, 0xb9, 0x6c, 0xc8, 0x3d, - 0xaf, 0xa5, 0xe4, 0x9e, 0x76, 0xf7, 0xda, 0xc7, 0x23, 0x08, 0x15, 0xce, 0x96, 0xcc, 0x17, 0xfd, - 0x21, 0x85, 0xa0, 0x86, 0xb3, 0xa5, 0x22, 0x84, 0x4d, 0xba, 0xdf, 0x48, 0xc2, 0xcf, 0x7f, 0x6f, - 0xc1, 0xb9, 0xcc, 0xb9, 0x39, 0x01, 0x61, 0xd7, 0x9a, 0x29, 0xec, 0x7a, 0xba, 0xef, 0xd5, 0x9a, - 0x23, 0xfd, 0xfa, 0xf5, 0x81, 0x9c, 0x6f, 0x61, 0x4f, 0xf9, 0xdb, 0x30, 0xe2, 0xd4, 0xeb, 0x24, - 0x8a, 0x56, 0x03, 0x57, 0x45, 0x79, 0x7d, 0x8e, 0xbd, 0xb3, 0x92, 0xe2, 0xc3, 0x83, 0xd9, 0x99, - 0x34, 0x89, 0x04, 0x8c, 0x75, 0x0a, 0xe8, 0xb3, 0x50, 0x8a, 0xc4, 0xbd, 0x29, 0xe6, 0xfe, 0x85, - 0x3e, 0x07, 0xc7, 0xd9, 0x20, 0x0d, 0x33, 0xc0, 0x8d, 0x12, 0x55, 0x28, 0x92, 0x66, 0x30, 0x8c, - 0xc2, 0xb1, 0x06, 0xc3, 0xb8, 0x06, 0xb0, 0xab, 0x1e, 0x03, 0x69, 0x01, 0x84, 0xf6, 0x4c, 0xd0, - 0xb0, 0xd0, 0xb7, 0xc0, 0x64, 0xc4, 0xc3, 0xb9, 0x2d, 0x36, 0x9c, 0x88, 0x79, 0x4c, 0x88, 0x55, - 0xc8, 0x82, 0xe8, 0xd4, 0x52, 0x30, 0xdc, 0x81, 0x8d, 0x96, 0x65, 0xab, 0x2c, 0xf6, 0x1c, 0x5f, - 0x98, 0x97, 0x93, 0x16, 0x45, 0x1a, 0xd2, 0xd3, 0xe9, 0xe1, 0x67, 0x03, 0xaf, 0xd5, 0x44, 0x9f, - 0x05, 0xa0, 0xcb, 0x47, 0x08, 0x22, 0x86, 0xf3, 0x0f, 0x4f, 0x7a, 0xaa, 0xb8, 0x99, 0x06, 0x9e, - 0xcc, 0xcd, 0xb1, 0xa2, 0x88, 0x60, 0x8d, 0xa0, 0xfd, 0x43, 0x03, 0xf0, 0x78, 0x97, 0x33, 0x12, - 0xcd, 0x9b, 0xca, 0xd2, 0x67, 0xd2, 0x8f, 0xeb, 0x99, 0xcc, 0xca, 0xc6, 0x6b, 0x3b, 0xb5, 0x14, - 0x0b, 0xef, 0x79, 0x29, 0x7e, 0xbf, 0xa5, 0x89, 0x3d, 0xb8, 0xd9, 0xdf, 0xa7, 0x8e, 0x78, 0xf6, - 0x1f, 0xa3, 0x1c, 0x64, 0x33, 0x43, 0x98, 0x70, 0xad, 0xef, 0xee, 0xf4, 0x2d, 0x5d, 0x38, 0x59, - 0x31, 0xf1, 0x17, 0x2c, 0x78, 0x32, 0xb3, 0xbf, 0x86, 0x71, 0xc7, 0x55, 0x28, 0xd7, 0x69, 0xa1, - 0xe6, 0xd5, 0x96, 0xb8, 0xfb, 0x4a, 0x00, 0x4e, 0x70, 0x0c, 0x1b, 0x8e, 0x42, 0x4f, 0x1b, 0x8e, - 0x7f, 0x65, 0x41, 0xc7, 0xfe, 0x38, 0x81, 0x83, 0x7a, 0xc5, 0x3c, 0xa8, 0x3f, 0xdc, 0xcf, 0x5c, - 0xe6, 0x9c, 0xd1, 0x7f, 0x34, 0x01, 0x67, 0x73, 0xbc, 0x3a, 0x76, 0x61, 0x6a, 0xab, 0x4e, 0x4c, - 0x7f, 0x41, 0xf1, 0x31, 0x99, 0xae, 0x95, 0x5d, 0x9d, 0x0b, 0x59, 0x4e, 0xc1, 0xa9, 0x0e, 0x14, - 0xdc, 0xd9, 0x04, 0xfa, 0x82, 0x05, 0xa7, 0x9d, 0xbd, 0xa8, 0x23, 0x09, 0xb9, 0x58, 0x33, 0x2f, - 0x66, 0x0a, 0x41, 0x7a, 0x24, 0x2d, 0xe7, 0x49, 0x16, 0xb3, 0xb0, 0x70, 0x66, 0x5b, 0x08, 0x8b, - 0xb8, 0xdf, 0x94, 0x9d, 0xef, 0xe2, 0xd1, 0x9a, 0xe5, 0x7e, 0xc3, 0x6f, 0x10, 0x09, 0xc1, 0x8a, - 0x0e, 0xfa, 0x3c, 0x94, 0xb7, 0xa4, 0x4f, 0x5c, 0xc6, 0x0d, 0x95, 0x0c, 0x64, 0x77, 0x4f, 0x41, - 0xae, 0xca, 0x54, 0x48, 0x38, 0x21, 0x8a, 0x5e, 0x83, 0xa2, 0xbf, 0x19, 0x75, 0xcb, 0x53, 0x98, - 0xb2, 0x7e, 0xe2, 0x7e, 0xe3, 0x6b, 0xcb, 0x35, 0x4c, 0x2b, 0xa2, 0x1b, 0x50, 0x0c, 0x37, 0x5c, - 0x21, 0xc1, 0xcb, 0x3c, 0xc3, 0xf1, 0x42, 0x25, 0xa7, 0x57, 0x8c, 0x12, 0x5e, 0xa8, 0x60, 0x4a, - 0x02, 0x55, 0x61, 0x90, 0xb9, 0x42, 0x88, 0xfb, 0x20, 0x93, 0xf3, 0xed, 0xe2, 0x52, 0xc4, 0x9d, - 0xcb, 0x19, 0x02, 0xe6, 0x84, 0xd0, 0x3a, 0x0c, 0xd5, 0x59, 0x4e, 0x3b, 0x11, 0x89, 0xea, 0x63, - 0x99, 0xb2, 0xba, 0x2e, 0xc9, 0xfe, 0x84, 0xe8, 0x8a, 0x61, 0x60, 0x41, 0x8b, 0x51, 0x25, 0xad, - 0xed, 0xcd, 0x48, 0xe4, 0x60, 0xcd, 0xa6, 0xda, 0x25, 0x87, 0xa5, 0xa0, 0xca, 0x30, 0xb0, 0xa0, - 0x85, 0x3e, 0x01, 0x85, 0xcd, 0xba, 0x70, 0x73, 0xc8, 0x14, 0xda, 0x99, 0xae, 0xff, 0x0b, 0x43, - 0x0f, 0x0e, 0x66, 0x0b, 0xcb, 0x8b, 0xb8, 0xb0, 0x59, 0x47, 0x6b, 0x30, 0xbc, 0xc9, 0x9d, 0x85, - 0x85, 0x5c, 0xee, 0xa9, 0x6c, 0x3f, 0xe6, 0x0e, 0x7f, 0x62, 0x6e, 0xe1, 0x2f, 0x00, 0x58, 0x12, - 0x61, 0x61, 0xb4, 0x95, 0xd3, 0xb3, 0x88, 0x02, 0x35, 0x77, 0x34, 0x47, 0x75, 0x7e, 0x3f, 0x27, - 0xae, 0xd3, 0x58, 0xa3, 0x48, 0x57, 0xb5, 0x23, 0x13, 0x61, 0x8b, 0xa8, 0x1e, 0x99, 0xab, 0xba, - 0x47, 0x8e, 0x70, 0xbe, 0xaa, 0x15, 0x12, 0x4e, 0x88, 0xa2, 0x1d, 0x18, 0xdb, 0x8d, 0x5a, 0xdb, - 0x44, 0x6e, 0x69, 0x16, 0xe4, 0x23, 0xe7, 0x0a, 0xbb, 0x2b, 0x10, 0xbd, 0x30, 0x6e, 0x3b, 0x8d, - 0x8e, 0x53, 0x88, 0xe9, 0xbf, 0xef, 0xea, 0xc4, 0xb0, 0x49, 0x9b, 0x0e, 0xff, 0x3b, 0xed, 0x60, - 0x63, 0x3f, 0x26, 0x22, 0x78, 0x53, 0xe6, 0xf0, 0xbf, 0xc1, 0x51, 0x3a, 0x87, 0x5f, 0x00, 0xb0, - 0x24, 0x82, 0xee, 0x8a, 0xe1, 0x61, 0xa7, 0xe7, 0x64, 0x7e, 0x40, 0xc4, 0xcc, 0x4c, 0xf4, 0xda, - 0xa0, 0xb0, 0xd3, 0x32, 0x21, 0xc5, 0x4e, 0xc9, 0xd6, 0x76, 0x10, 0x07, 0x7e, 0xea, 0x84, 0x9e, - 0xca, 0x3f, 0x25, 0xab, 0x19, 0xf8, 0x9d, 0xa7, 0x64, 0x16, 0x16, 0xce, 0x6c, 0x0b, 0xb9, 0x30, - 0xde, 0x0a, 0xc2, 0x78, 0x2f, 0x08, 0xe5, 0xfa, 0x42, 0x5d, 0xe4, 0x0a, 0x06, 0xa6, 0x68, 0x91, - 0x85, 0x31, 0x33, 0x21, 0x38, 0x45, 0x13, 0x7d, 0x1a, 0x86, 0xa3, 0xba, 0xd3, 0x20, 0x2b, 0xb7, - 0xa7, 0x4f, 0xe5, 0x5f, 0x3f, 0x35, 0x8e, 0x92, 0xb3, 0xba, 0xd8, 0xe4, 0x08, 0x14, 0x2c, 0xc9, - 0xa1, 0x65, 0x18, 0x64, 0x59, 0x8d, 0x58, 0xa4, 0xb1, 0x9c, 0xb8, 0x8e, 0x1d, 0xb6, 0xa8, 0xfc, - 0x6c, 0x62, 0xc5, 0x98, 0x57, 0xa7, 0x7b, 0x40, 0xb0, 0xd7, 0x41, 0x34, 0x7d, 0x26, 0x7f, 0x0f, - 0x08, 0xae, 0xfc, 0x76, 0xad, 0xdb, 0x1e, 0x50, 0x48, 0x38, 0x21, 0x4a, 0x4f, 0x66, 0x7a, 0x9a, - 0x9e, 0xed, 0x62, 0xfa, 0x92, 0x7b, 0x96, 0xb2, 0x93, 0x99, 0x9e, 0xa4, 0x94, 0x84, 0xfd, 0x3b, - 0xc3, 0x9d, 0x3c, 0x0b, 0x7b, 0x90, 0xfd, 0x55, 0xab, 0x43, 0x57, 0xf7, 0xf1, 0x7e, 0xe5, 0x43, - 0xc7, 0xc8, 0xad, 0x7e, 0xc1, 0x82, 0xb3, 0xad, 0xcc, 0x0f, 0x11, 0x0c, 0x40, 0x7f, 0x62, 0x26, - 0xfe, 0xe9, 0x2a, 0x2a, 0x5d, 0x36, 0x1c, 0xe7, 0xb4, 0x94, 0x7e, 0x11, 0x14, 0xdf, 0xf3, 0x8b, - 0x60, 0x15, 0x4a, 0x8c, 0xc9, 0xec, 0x91, 0xe3, 0x35, 0xfd, 0x30, 0x62, 0xac, 0xc4, 0xa2, 0xa8, - 0x88, 0x15, 0x09, 0xf4, 0x03, 0x16, 0x9c, 0x4f, 0x77, 0x1d, 0x13, 0x06, 0x16, 0xa1, 0xec, 0xf8, - 0x5b, 0x70, 0x59, 0x7c, 0xff, 0xf9, 0x6a, 0x37, 0xe4, 0xc3, 0x5e, 0x08, 0xb8, 0x7b, 0x63, 0xa8, - 0x92, 0xf1, 0x18, 0x1d, 0x32, 0x05, 0xf0, 0x7d, 0x3c, 0x48, 0x5f, 0x84, 0xd1, 0x66, 0xd0, 0xf6, - 0x63, 0x61, 0x29, 0x23, 0xb4, 0xf6, 0x4c, 0x5b, 0xbd, 0xaa, 0x95, 0x63, 0x03, 0x2b, 0xf5, 0x8c, - 0x2d, 0x3d, 0xf4, 0x33, 0xf6, 0x2d, 0x18, 0xf5, 0x35, 0xd3, 0x4e, 0xc1, 0x0f, 0x5c, 0xce, 0x8f, - 0x1a, 0xa9, 0x1b, 0x82, 0xf2, 0x5e, 0xea, 0x25, 0xd8, 0xa0, 0x76, 0xb2, 0x6f, 0xa3, 0x9f, 0xb6, - 0x32, 0x98, 0x7a, 0xfe, 0x5a, 0xfe, 0xa4, 0xf9, 0x5a, 0xbe, 0x9c, 0x7e, 0x2d, 0x77, 0x08, 0x5f, - 0x8d, 0x87, 0x72, 0xff, 0xa9, 0x2b, 0xfa, 0x8d, 0x38, 0x67, 0x37, 0xe0, 0x62, 0xaf, 0x6b, 0x89, - 0x99, 0x4c, 0xb9, 0x4a, 0xd5, 0x96, 0x98, 0x4c, 0xb9, 0x2b, 0x15, 0xcc, 0x20, 0xfd, 0x86, 0x24, - 0xb1, 0xff, 0x97, 0x05, 0xc5, 0x6a, 0xe0, 0x9e, 0x80, 0x30, 0xf9, 0x53, 0x86, 0x30, 0xf9, 0xf1, - 0xec, 0x0b, 0xd1, 0xcd, 0x15, 0x1d, 0x2f, 0xa5, 0x44, 0xc7, 0xe7, 0xf3, 0x08, 0x74, 0x17, 0x14, - 0xff, 0x44, 0x11, 0x46, 0xaa, 0x81, 0xab, 0xec, 0x95, 0x7f, 0xfd, 0x61, 0xec, 0x95, 0x73, 0x43, - 0xbb, 0x6b, 0x94, 0x99, 0xa5, 0x95, 0x74, 0xd7, 0xfb, 0x0b, 0x66, 0xb6, 0x7c, 0x8f, 0x78, 0x5b, - 0xdb, 0x31, 0x71, 0xd3, 0x9f, 0x73, 0x72, 0x66, 0xcb, 0xff, 0xd3, 0x82, 0x89, 0x54, 0xeb, 0xa8, - 0x01, 0x63, 0x0d, 0x5d, 0x30, 0x29, 0xd6, 0xe9, 0x43, 0xc9, 0x34, 0x85, 0xd9, 0xa7, 0x56, 0x84, - 0x4d, 0xe2, 0x68, 0x0e, 0x40, 0x69, 0xea, 0xa4, 0x04, 0x8c, 0x71, 0xfd, 0x4a, 0x95, 0x17, 0x61, - 0x0d, 0x03, 0xbd, 0x04, 0x23, 0x71, 0xd0, 0x0a, 0x1a, 0xc1, 0xd6, 0xfe, 0x4d, 0x22, 0x83, 0xe0, - 0x28, 0x63, 0xae, 0xf5, 0x04, 0x84, 0x75, 0x3c, 0xfb, 0xa7, 0x8a, 0xfc, 0x43, 0xfd, 0xd8, 0xfb, - 0x60, 0x4d, 0xbe, 0xbf, 0xd7, 0xe4, 0xd7, 0x2c, 0x98, 0xa4, 0xad, 0x33, 0x73, 0x11, 0x79, 0xd9, - 0xaa, 0xf0, 0xb3, 0x56, 0x97, 0xf0, 0xb3, 0x97, 0xe9, 0xd9, 0xe5, 0x06, 0xed, 0x58, 0x48, 0xd0, - 0xb4, 0xc3, 0x89, 0x96, 0x62, 0x01, 0x15, 0x78, 0x24, 0x0c, 0x85, 0xb7, 0x94, 0x8e, 0x47, 0xc2, - 0x10, 0x0b, 0xa8, 0x8c, 0x4e, 0x3b, 0x90, 0x1d, 0x9d, 0x96, 0x87, 0xf4, 0x13, 0x86, 0x05, 0x82, - 0xed, 0xd1, 0x42, 0xfa, 0x49, 0x8b, 0x83, 0x04, 0xc7, 0xfe, 0x72, 0x11, 0x46, 0xab, 0x81, 0x9b, - 0xe8, 0xca, 0x5e, 0x34, 0x74, 0x65, 0x17, 0x53, 0xba, 0xb2, 0x49, 0x1d, 0xf7, 0x03, 0xcd, 0xd8, - 0xd7, 0x4b, 0x33, 0xf6, 0x2f, 0x2d, 0x36, 0x6b, 0x95, 0xb5, 0x9a, 0xc8, 0xf0, 0xff, 0x3c, 0x8c, - 0xb0, 0x03, 0x89, 0xb9, 0xe7, 0x49, 0x05, 0x12, 0x4b, 0x9e, 0xb3, 0x96, 0x14, 0x63, 0x1d, 0x07, - 0x5d, 0x81, 0x52, 0x44, 0x9c, 0xb0, 0xbe, 0xad, 0xce, 0x38, 0xa1, 0xed, 0xe1, 0x65, 0x58, 0x41, - 0xd1, 0x1b, 0x49, 0x34, 0xb9, 0x62, 0x7e, 0xb0, 0x61, 0xbd, 0x3f, 0x7c, 0x8b, 0xe4, 0x87, 0x90, - 0xb3, 0xef, 0x01, 0xea, 0xc4, 0xef, 0x23, 0x8c, 0xd2, 0xac, 0x19, 0x46, 0xa9, 0xdc, 0x11, 0x42, - 0xe9, 0xcf, 0x2c, 0x18, 0xaf, 0x06, 0x2e, 0xdd, 0xba, 0xdf, 0x48, 0xfb, 0x54, 0x0f, 0xa5, 0x39, - 0xd4, 0x25, 0x94, 0xe6, 0x25, 0x18, 0xac, 0x06, 0xee, 0x4a, 0xb5, 0x9b, 0x9b, 0xac, 0xfd, 0x0f, - 0x2c, 0x18, 0xae, 0x06, 0xee, 0x09, 0x08, 0xe7, 0x3f, 0x69, 0x0a, 0xe7, 0x1f, 0xcb, 0x59, 0x37, - 0x39, 0xf2, 0xf8, 0x5f, 0x28, 0xc2, 0x18, 0xed, 0x67, 0xb0, 0x25, 0xa7, 0xd2, 0x18, 0x36, 0xab, - 0x8f, 0x61, 0xa3, 0xbc, 0x70, 0xd0, 0x68, 0x04, 0x7b, 0xe9, 0x69, 0x5d, 0x66, 0xa5, 0x58, 0x40, - 0xd1, 0xb3, 0x50, 0x6a, 0x85, 0x64, 0xd7, 0x0b, 0x04, 0x93, 0xa9, 0xa9, 0x3a, 0xaa, 0xa2, 0x1c, - 0x2b, 0x0c, 0xfa, 0x38, 0x8b, 0x3c, 0xbf, 0x4e, 0x6a, 0xa4, 0x1e, 0xf8, 0x2e, 0x97, 0x5f, 0x17, - 0x45, 0x8a, 0x0b, 0xad, 0x1c, 0x1b, 0x58, 0xe8, 0x1e, 0x94, 0xd9, 0x7f, 0x76, 0xec, 0x1c, 0x3d, - 0x41, 0xa0, 0xc8, 0x2b, 0x25, 0x08, 0xe0, 0x84, 0x16, 0xba, 0x06, 0x10, 0xcb, 0x60, 0xcb, 0x91, - 0x08, 0x99, 0xa3, 0x18, 0x72, 0x15, 0x86, 0x39, 0xc2, 0x1a, 0x16, 0x7a, 0x06, 0xca, 0xb1, 0xe3, - 0x35, 0x6e, 0x79, 0x3e, 0x89, 0x98, 0x5c, 0xba, 0x28, 0xd3, 0x3b, 0x89, 0x42, 0x9c, 0xc0, 0x29, - 0x43, 0xc4, 0xfc, 0xc9, 0x79, 0x7a, 0xd1, 0x12, 0xc3, 0x66, 0x0c, 0xd1, 0x2d, 0x55, 0x8a, 0x35, - 0x0c, 0xfb, 0x15, 0x38, 0x53, 0x0d, 0xdc, 0x6a, 0x10, 0xc6, 0xcb, 0x41, 0xb8, 0xe7, 0x84, 0xae, - 0x9c, 0xbf, 0x59, 0x99, 0x15, 0x82, 0x1e, 0x50, 0x83, 0x7c, 0xfb, 0x1a, 0xb9, 0x89, 0x5e, 0x60, - 0x2c, 0xd1, 0x11, 0x7d, 0x44, 0xea, 0xec, 0x72, 0x56, 0xf1, 0xff, 0xaf, 0x3b, 0x31, 0x41, 0xb7, - 0x59, 0xf6, 0xd1, 0xe4, 0x9e, 0x12, 0xd5, 0x9f, 0xd6, 0xb2, 0x8f, 0x26, 0xc0, 0xcc, 0x8b, 0xcd, - 0xac, 0x6f, 0xff, 0xec, 0x00, 0x3b, 0xb2, 0x52, 0x41, 0xe9, 0xd1, 0xe7, 0x60, 0x3c, 0x22, 0xb7, - 0x3c, 0xbf, 0x7d, 0x5f, 0xbe, 0xd4, 0xbb, 0x78, 0xf9, 0xd4, 0x96, 0x74, 0x4c, 0x2e, 0xef, 0x33, - 0xcb, 0x70, 0x8a, 0x1a, 0x6a, 0xc2, 0xf8, 0x9e, 0xe7, 0xbb, 0xc1, 0x5e, 0x24, 0xe9, 0x97, 0xf2, - 0xc5, 0x7e, 0xf7, 0x38, 0x66, 0xaa, 0x8f, 0x46, 0x73, 0xf7, 0x0c, 0x62, 0x38, 0x45, 0x9c, 0x2e, - 0x8b, 0xb0, 0xed, 0xcf, 0x47, 0x77, 0x22, 0x12, 0x8a, 0x3c, 0xb2, 0x6c, 0x59, 0x60, 0x59, 0x88, - 0x13, 0x38, 0x5d, 0x16, 0xec, 0xcf, 0xf5, 0x30, 0x68, 0xf3, 0x40, 0xe5, 0x62, 0x59, 0x60, 0x55, - 0x8a, 0x35, 0x0c, 0xba, 0x6d, 0xd8, 0xbf, 0xb5, 0xc0, 0xc7, 0x41, 0x10, 0xcb, 0x8d, 0xc6, 0x32, - 0x17, 0x6a, 0xe5, 0xd8, 0xc0, 0x42, 0xcb, 0x80, 0xa2, 0x76, 0xab, 0xd5, 0x60, 0xd6, 0x03, 0x4e, - 0x83, 0x91, 0xe2, 0x9a, 0xdb, 0x22, 0x0f, 0xc3, 0x58, 0xeb, 0x80, 0xe2, 0x8c, 0x1a, 0xf4, 0x04, - 0xdd, 0x14, 0x5d, 0x1d, 0x64, 0x5d, 0xe5, 0x2a, 0x82, 0x1a, 0xef, 0xa7, 0x84, 0xa1, 0x25, 0x18, - 0x8e, 0xf6, 0xa3, 0x7a, 0x2c, 0xe2, 0x49, 0xe5, 0xa4, 0x09, 0xa9, 0x31, 0x14, 0x2d, 0x4b, 0x15, - 0xaf, 0x82, 0x65, 0x5d, 0xfb, 0x3b, 0xd8, 0x05, 0xcd, 0xb2, 0x8e, 0xc6, 0xed, 0x90, 0xa0, 0x26, - 0x8c, 0xb5, 0xd8, 0x0a, 0x13, 0x91, 0xb7, 0xc5, 0x32, 0x79, 0xb1, 0xcf, 0x97, 0xf6, 0x1e, 0x3d, - 0xd7, 0x94, 0x24, 0x8c, 0x3d, 0x61, 0xaa, 0x3a, 0x39, 0x6c, 0x52, 0xb7, 0xbf, 0x76, 0x96, 0x1d, - 0xf1, 0x35, 0xfe, 0x7c, 0x1e, 0x16, 0xe6, 0xce, 0xe2, 0xad, 0x30, 0x93, 0x2f, 0xc7, 0x49, 0xbe, - 0x48, 0x98, 0x4c, 0x63, 0x59, 0x17, 0x7d, 0x16, 0xc6, 0x29, 0xeb, 0xad, 0x65, 0x1e, 0x38, 0x9d, - 0xef, 0x3a, 0x9e, 0x24, 0x1c, 0xd0, 0xa2, 0xf2, 0xeb, 0x95, 0x71, 0x8a, 0x18, 0x7a, 0x83, 0x29, - 0xe6, 0xcd, 0xa4, 0x06, 0x3d, 0x48, 0xeb, 0x3a, 0x78, 0x49, 0x56, 0x23, 0x92, 0x97, 0x30, 0xc1, - 0x7e, 0xb4, 0x09, 0x13, 0xd0, 0x2d, 0x18, 0x13, 0xa9, 0x37, 0x85, 0xf8, 0xb1, 0x68, 0x88, 0x97, - 0xc6, 0xb0, 0x0e, 0x3c, 0x4c, 0x17, 0x60, 0xb3, 0x32, 0xda, 0x82, 0xf3, 0x5a, 0xd6, 0x8e, 0xeb, - 0xa1, 0xc3, 0x74, 0xc4, 0x1e, 0x3b, 0x89, 0xb4, 0xcb, 0xe7, 0xc9, 0x07, 0x07, 0xb3, 0xe7, 0xd7, - 0xbb, 0x21, 0xe2, 0xee, 0x74, 0xd0, 0x6d, 0x38, 0xc3, 0xbd, 0x2a, 0x2b, 0xc4, 0x71, 0x1b, 0x9e, - 0xaf, 0x6e, 0x37, 0xbe, 0x5b, 0xce, 0x3d, 0x38, 0x98, 0x3d, 0x33, 0x9f, 0x85, 0x80, 0xb3, 0xeb, - 0xa1, 0x4f, 0x42, 0xd9, 0xf5, 0x23, 0x31, 0x06, 0x43, 0x46, 0x62, 0x94, 0x72, 0x65, 0xad, 0xa6, - 0xbe, 0x3f, 0xf9, 0x83, 0x93, 0x0a, 0x68, 0x8b, 0x8b, 0x20, 0xd5, 0x8b, 0x7f, 0xb8, 0x23, 0xb2, - 0x48, 0x5a, 0x76, 0x64, 0xf8, 0x55, 0x71, 0xd9, 0xbb, 0xb2, 0x36, 0x36, 0x5c, 0xae, 0x0c, 0xc2, - 0xe8, 0x75, 0x40, 0x94, 0x25, 0xf6, 0xea, 0x64, 0xbe, 0xce, 0xc2, 0xba, 0x33, 0x89, 0x6d, 0xc9, - 0xf0, 0x4e, 0x41, 0xb5, 0x0e, 0x0c, 0x9c, 0x51, 0x0b, 0xdd, 0xa0, 0xb7, 0x81, 0x5e, 0x2a, 0xac, - 0xa6, 0x55, 0xd6, 0xa9, 0x0a, 0x69, 0x85, 0xa4, 0xee, 0xc4, 0xc4, 0x35, 0x29, 0xe2, 0x54, 0x3d, - 0xe4, 0xc2, 0x13, 0x4e, 0x3b, 0x0e, 0x98, 0x74, 0xd7, 0x44, 0x5d, 0x0f, 0x76, 0x88, 0xcf, 0x14, - 0x2b, 0xa5, 0x85, 0x8b, 0x0f, 0x0e, 0x66, 0x9f, 0x98, 0xef, 0x82, 0x87, 0xbb, 0x52, 0xa1, 0x6c, - 0x8f, 0xca, 0x19, 0x09, 0x66, 0xc0, 0x94, 0x8c, 0xbc, 0x91, 0x2f, 0xc1, 0xc8, 0x76, 0x10, 0xc5, - 0x6b, 0x24, 0xde, 0x0b, 0xc2, 0x1d, 0x11, 0xf6, 0x2e, 0x09, 0x95, 0x9a, 0x80, 0xb0, 0x8e, 0x47, - 0xdf, 0x35, 0x4c, 0xed, 0xbf, 0x52, 0x61, 0x1a, 0xd7, 0x52, 0x72, 0xc6, 0xdc, 0xe0, 0xc5, 0x58, - 0xc2, 0x25, 0xea, 0x4a, 0x75, 0x91, 0x69, 0x4f, 0x53, 0xa8, 0x2b, 0xd5, 0x45, 0x2c, 0xe1, 0x74, - 0xb9, 0x46, 0xdb, 0x4e, 0x48, 0xaa, 0x61, 0x50, 0x27, 0x91, 0x16, 0xa0, 0xf7, 0x71, 0x1e, 0xd4, - 0x8f, 0x2e, 0xd7, 0x5a, 0x16, 0x02, 0xce, 0xae, 0x87, 0x48, 0x67, 0xc6, 0x9a, 0xf1, 0x7c, 0xb1, - 0x77, 0x27, 0x2b, 0xd0, 0x67, 0xd2, 0x1a, 0x1f, 0x26, 0x55, 0xae, 0x1c, 0x1e, 0xc6, 0x2f, 0x9a, - 0x9e, 0x60, 0x6b, 0xbb, 0xff, 0x18, 0x80, 0x4a, 0x91, 0xb0, 0x92, 0xa2, 0x84, 0x3b, 0x68, 0x1b, - 0x31, 0x71, 0x26, 0x7b, 0x26, 0x11, 0xbd, 0x0a, 0xe5, 0xa8, 0xbd, 0xe1, 0x06, 0x4d, 0xc7, 0xf3, - 0x99, 0xf6, 0x54, 0x63, 0xb0, 0x6b, 0x12, 0x80, 0x13, 0x1c, 0xb4, 0x0c, 0x25, 0x47, 0x6a, 0x09, - 0x50, 0x7e, 0x00, 0x0c, 0xa5, 0x1b, 0xe0, 0x3e, 0xe1, 0x52, 0x2f, 0xa0, 0xea, 0xa2, 0x57, 0x61, - 0x4c, 0x78, 0x05, 0x8a, 0xac, 0x6a, 0xa7, 0x4c, 0xcf, 0x8d, 0x9a, 0x0e, 0xc4, 0x26, 0x2e, 0xba, - 0x03, 0x23, 0x71, 0xd0, 0x60, 0xee, 0x07, 0x94, 0x43, 0x3a, 0x9b, 0x1f, 0x8e, 0x69, 0x5d, 0xa1, - 0xe9, 0x02, 0x3a, 0x55, 0x15, 0xeb, 0x74, 0xd0, 0x3a, 0x5f, 0xef, 0x2c, 0x50, 0x2d, 0x89, 0xa6, - 0x1f, 0xcb, 0xbf, 0x93, 0x54, 0x3c, 0x5b, 0x73, 0x3b, 0x88, 0x9a, 0x58, 0x27, 0x83, 0xae, 0xc3, - 0x54, 0x2b, 0xf4, 0x02, 0xb6, 0x26, 0x94, 0x82, 0x68, 0xda, 0x4c, 0xaf, 0x51, 0x4d, 0x23, 0xe0, - 0xce, 0x3a, 0xcc, 0xa9, 0x53, 0x14, 0x4e, 0x9f, 0xe3, 0x59, 0x54, 0xf9, 0x7b, 0x85, 0x97, 0x61, - 0x05, 0x45, 0xab, 0xec, 0x24, 0xe6, 0x4f, 0xed, 0xe9, 0x99, 0xfc, 0x98, 0x1b, 0xfa, 0x93, 0x9c, - 0xf3, 0x7d, 0xea, 0x2f, 0x4e, 0x28, 0x20, 0x57, 0xcb, 0xd0, 0x45, 0x99, 0xed, 0x68, 0xfa, 0x89, - 0x2e, 0xb6, 0x57, 0x29, 0xce, 0x3c, 0x61, 0x08, 0x8c, 0xe2, 0x08, 0xa7, 0x68, 0xa2, 0x6f, 0x81, - 0x49, 0x11, 0x2d, 0x2a, 0x19, 0xa6, 0xf3, 0x89, 0x51, 0x27, 0x4e, 0xc1, 0x70, 0x07, 0x36, 0x0f, - 0xe0, 0xed, 0x6c, 0x34, 0x88, 0x38, 0xfa, 0x6e, 0x79, 0xfe, 0x4e, 0x34, 0x7d, 0x81, 0x9d, 0x0f, - 0x22, 0x80, 0x77, 0x1a, 0x8a, 0x33, 0x6a, 0xa0, 0x75, 0x98, 0x6c, 0x85, 0x84, 0x34, 0x19, 0x8f, - 0x2c, 0xee, 0xb3, 0x59, 0xee, 0xd3, 0x4c, 0x7b, 0x52, 0x4d, 0xc1, 0x0e, 0x33, 0xca, 0x70, 0x07, - 0x05, 0xb4, 0x07, 0xa5, 0x60, 0x97, 0x84, 0xdb, 0xc4, 0x71, 0xa7, 0x2f, 0x76, 0x31, 0x32, 0x16, - 0x97, 0xdb, 0x6d, 0x81, 0x9b, 0x52, 0x2a, 0xcb, 0xe2, 0xde, 0x4a, 0x65, 0xd9, 0x18, 0xfa, 0x41, - 0x0b, 0xce, 0x49, 0x39, 0x74, 0xad, 0x45, 0x47, 0x7d, 0x31, 0xf0, 0xa3, 0x38, 0xe4, 0x5e, 0xb8, - 0x4f, 0xe6, 0x3b, 0xa6, 0xae, 0xe7, 0x54, 0x52, 0xd2, 0xbe, 0x73, 0x79, 0x18, 0x11, 0xce, 0x6f, - 0x71, 0xe6, 0x9b, 0x61, 0xaa, 0xe3, 0xe6, 0x3e, 0x4a, 0x4e, 0x81, 0x99, 0x1d, 0x18, 0x33, 0x46, - 0xe7, 0x91, 0xea, 0x13, 0xff, 0xdd, 0x30, 0x94, 0x95, 0xae, 0x09, 0x5d, 0x35, 0x55, 0x88, 0xe7, - 0xd2, 0x2a, 0xc4, 0x12, 0x7d, 0xcd, 0xea, 0x5a, 0xc3, 0x75, 0xc3, 0xfe, 0xb4, 0x90, 0x9f, 0x8d, - 0x4f, 0x7f, 0x8f, 0xf6, 0xf4, 0x65, 0xd5, 0x44, 0x87, 0xc5, 0xbe, 0x75, 0x91, 0x03, 0x5d, 0xa5, - 0x91, 0xd7, 0x61, 0xca, 0x0f, 0x18, 0xbb, 0x48, 0x5c, 0xc9, 0x0b, 0xb0, 0x2b, 0xbf, 0xac, 0x07, - 0x11, 0x48, 0x21, 0xe0, 0xce, 0x3a, 0xb4, 0x41, 0x7e, 0x67, 0xa7, 0xc5, 0x9f, 0xfc, 0x4a, 0xc7, - 0x02, 0x8a, 0x2e, 0xc1, 0x60, 0x2b, 0x70, 0x57, 0xaa, 0xe9, 0x0c, 0xf5, 0x4c, 0x9e, 0x85, 0x39, - 0x0c, 0xcd, 0xc3, 0x10, 0xfb, 0x11, 0x4d, 0x8f, 0xe6, 0x7b, 0x8b, 0xb3, 0x1a, 0x5a, 0xc6, 0x06, - 0x56, 0x01, 0x8b, 0x8a, 0x4c, 0x0c, 0x43, 0xf9, 0x6b, 0x26, 0x86, 0x19, 0x7e, 0x48, 0x31, 0x8c, - 0x24, 0x80, 0x13, 0x5a, 0xe8, 0x3e, 0x9c, 0x31, 0xde, 0x34, 0x7c, 0x89, 0x90, 0x48, 0x38, 0xac, - 0x5e, 0xea, 0xfa, 0x98, 0x11, 0xba, 0xcb, 0xf3, 0xa2, 0xd3, 0x67, 0x56, 0xb2, 0x28, 0xe1, 0xec, - 0x06, 0x50, 0x03, 0xa6, 0xea, 0x1d, 0xad, 0x96, 0xfa, 0x6f, 0x55, 0x4d, 0x68, 0x67, 0x8b, 0x9d, - 0x84, 0xd1, 0xab, 0x50, 0x7a, 0x27, 0x88, 0xd8, 0x31, 0x2b, 0xd8, 0x5b, 0xe9, 0xed, 0x58, 0x7a, - 0xe3, 0x76, 0x8d, 0x95, 0x1f, 0x1e, 0xcc, 0x8e, 0x54, 0x03, 0x57, 0xfe, 0xc5, 0xaa, 0x02, 0xfa, - 0x5e, 0x0b, 0x66, 0x3a, 0x1f, 0x4d, 0xaa, 0xd3, 0x63, 0xfd, 0x77, 0xda, 0x16, 0x8d, 0xce, 0x2c, - 0xe5, 0x92, 0xc3, 0x5d, 0x9a, 0xb2, 0x7f, 0x99, 0xeb, 0x19, 0x85, 0x36, 0x82, 0x44, 0xed, 0xc6, - 0x49, 0x64, 0xb8, 0x5b, 0x32, 0x14, 0x25, 0x0f, 0xad, 0xcb, 0xfe, 0x35, 0x8b, 0xe9, 0xb2, 0xd7, - 0x49, 0xb3, 0xd5, 0x70, 0xe2, 0x93, 0x70, 0x96, 0x7b, 0x03, 0x4a, 0xb1, 0x68, 0xad, 0x5b, 0x52, - 0x3e, 0xad, 0x53, 0x4c, 0x9f, 0xaf, 0x98, 0x4d, 0x59, 0x8a, 0x15, 0x19, 0xfb, 0x9f, 0xf1, 0x19, - 0x90, 0x90, 0x13, 0x90, 0x47, 0x57, 0x4c, 0x79, 0xf4, 0x6c, 0x8f, 0x2f, 0xc8, 0x91, 0x4b, 0xff, - 0x53, 0xb3, 0xdf, 0x4c, 0xc8, 0xf2, 0x7e, 0x37, 0xa2, 0xb0, 0x7f, 0xd8, 0x82, 0xd3, 0x59, 0x56, - 0x87, 0xf4, 0x81, 0xc0, 0x45, 0x3c, 0xca, 0xa8, 0x44, 0x8d, 0xe0, 0x5d, 0x51, 0x8e, 0x15, 0x46, - 0xdf, 0xf9, 0x6e, 0x8e, 0x16, 0xff, 0xf1, 0x36, 0x8c, 0x55, 0x43, 0xa2, 0x5d, 0x68, 0xaf, 0x71, - 0xef, 0x57, 0xde, 0x9f, 0x67, 0x8f, 0xec, 0xf9, 0x6a, 0xff, 0x4c, 0x01, 0x4e, 0x73, 0xad, 0xf0, - 0xfc, 0x6e, 0xe0, 0xb9, 0xd5, 0xc0, 0x15, 0xb9, 0x8a, 0xde, 0x84, 0xd1, 0x96, 0x26, 0x97, 0xeb, - 0x16, 0x81, 0x4e, 0x97, 0xdf, 0x25, 0x92, 0x04, 0xbd, 0x14, 0x1b, 0xb4, 0x90, 0x0b, 0xa3, 0x64, - 0xd7, 0xab, 0x2b, 0xd5, 0x62, 0xe1, 0xc8, 0x97, 0x8b, 0x6a, 0x65, 0x49, 0xa3, 0x83, 0x0d, 0xaa, - 0x8f, 0x20, 0x7d, 0xa5, 0xfd, 0x23, 0x16, 0x3c, 0x96, 0x13, 0xaf, 0x8e, 0x36, 0xb7, 0xc7, 0xf4, - 0xef, 0x22, 0x13, 0x9e, 0x6a, 0x8e, 0x6b, 0xe5, 0xb1, 0x80, 0xa2, 0x4f, 0x03, 0x70, 0xad, 0x3a, - 0x7d, 0xa1, 0xf6, 0x0a, 0xec, 0x65, 0xc4, 0x24, 0xd2, 0xc2, 0xcb, 0xc8, 0xfa, 0x58, 0xa3, 0x65, - 0xff, 0x64, 0x11, 0x06, 0x79, 0x0e, 0xdf, 0x65, 0x18, 0xde, 0xe6, 0x11, 0xdc, 0xfb, 0x09, 0x16, - 0x9f, 0xc8, 0x0e, 0x78, 0x01, 0x96, 0x95, 0xd1, 0x2a, 0x9c, 0xe2, 0x11, 0xf0, 0x1b, 0x15, 0xd2, - 0x70, 0xf6, 0xa5, 0xa0, 0x8b, 0x67, 0x8f, 0x53, 0x02, 0xbf, 0x95, 0x4e, 0x14, 0x9c, 0x55, 0x0f, - 0xbd, 0x06, 0xe3, 0xf4, 0xe1, 0x11, 0xb4, 0x63, 0x49, 0x89, 0xc7, 0xbe, 0x57, 0x2f, 0x9d, 0x75, - 0x03, 0x8a, 0x53, 0xd8, 0xf4, 0xed, 0xdb, 0xea, 0x10, 0xe9, 0x0d, 0x26, 0x6f, 0x5f, 0x53, 0x8c, - 0x67, 0xe2, 0x32, 0x73, 0xc3, 0x36, 0x33, 0xae, 0x5c, 0xdf, 0x0e, 0x49, 0xb4, 0x1d, 0x34, 0x5c, - 0xc6, 0x68, 0x0d, 0x6a, 0xe6, 0x86, 0x29, 0x38, 0xee, 0xa8, 0x41, 0xa9, 0x6c, 0x3a, 0x5e, 0xa3, - 0x1d, 0x92, 0x84, 0xca, 0x90, 0x49, 0x65, 0x39, 0x05, 0xc7, 0x1d, 0x35, 0xe8, 0x3a, 0x3a, 0x53, - 0x0d, 0x03, 0x7a, 0x78, 0xc9, 0x18, 0x1c, 0xca, 0x86, 0x74, 0x58, 0xba, 0x0b, 0x76, 0x09, 0x57, - 0x25, 0xac, 0xec, 0x38, 0x05, 0x43, 0x81, 0x5c, 0x13, 0x8e, 0x82, 0x92, 0x0a, 0x7a, 0x1e, 0x46, - 0x44, 0x5c, 0x73, 0x66, 0xea, 0xc8, 0xa7, 0x8e, 0x29, 0xbc, 0x2b, 0x49, 0x31, 0xd6, 0x71, 0xec, - 0xef, 0x2b, 0xc0, 0xa9, 0x0c, 0x5b, 0x75, 0x7e, 0x54, 0x6d, 0x79, 0x51, 0xac, 0x32, 0x64, 0x69, - 0x47, 0x15, 0x2f, 0xc7, 0x0a, 0x83, 0xee, 0x07, 0x7e, 0x18, 0xa6, 0x0f, 0x40, 0x61, 0x0b, 0x2a, - 0xa0, 0x47, 0xcc, 0x35, 0x75, 0x11, 0x06, 0xda, 0x11, 0x91, 0x81, 0xe6, 0xd4, 0xf9, 0xcd, 0x34, - 0x2e, 0x0c, 0x42, 0xd9, 0xe3, 0x2d, 0xa5, 0xbc, 0xd0, 0xd8, 0x63, 0xae, 0xbe, 0xe0, 0x30, 0xda, - 0xb9, 0x98, 0xf8, 0x8e, 0x1f, 0x0b, 0x26, 0x3a, 0x89, 0x98, 0xc4, 0x4a, 0xb1, 0x80, 0xda, 0x5f, - 0x2a, 0xc2, 0xb9, 0x5c, 0xef, 0x15, 0xda, 0xf5, 0x66, 0xe0, 0x7b, 0x71, 0xa0, 0x2c, 0x09, 0x78, - 0x94, 0x24, 0xd2, 0xda, 0x5e, 0x15, 0xe5, 0x58, 0x61, 0xa0, 0xcb, 0x66, 0x1e, 0xfa, 0xe4, 0x2b, - 0x17, 0x2a, 0x46, 0x2a, 0xfa, 0x7e, 0xf3, 0x30, 0x5e, 0x82, 0x81, 0x56, 0x10, 0x34, 0xd2, 0x87, - 0x16, 0xed, 0x6e, 0x10, 0x34, 0x30, 0x03, 0xa2, 0x8f, 0x88, 0xf1, 0x4a, 0xa9, 0xce, 0xb1, 0xe3, - 0x06, 0x91, 0x36, 0x68, 0x4f, 0xc3, 0xf0, 0x0e, 0xd9, 0x0f, 0x3d, 0x7f, 0x2b, 0x6d, 0x52, 0x71, - 0x93, 0x17, 0x63, 0x09, 0x37, 0xd3, 0xbe, 0x0c, 0x1f, 0x77, 0x02, 0xc5, 0x52, 0xcf, 0x2b, 0xf0, - 0xfb, 0x8b, 0x30, 0x81, 0x17, 0x2a, 0x1f, 0x4c, 0xc4, 0x9d, 0xce, 0x89, 0x38, 0xee, 0x04, 0x8a, - 0xbd, 0x67, 0xe3, 0x17, 0x2c, 0x98, 0x60, 0xd1, 0xd5, 0x45, 0x78, 0x1d, 0x2f, 0xf0, 0x4f, 0x80, - 0xc5, 0xbb, 0x04, 0x83, 0x21, 0x6d, 0x34, 0x9d, 0x24, 0x8c, 0xf5, 0x04, 0x73, 0x18, 0x7a, 0x02, - 0x06, 0x58, 0x17, 0xe8, 0xe4, 0x8d, 0xf2, 0xfc, 0x2a, 0x15, 0x27, 0x76, 0x30, 0x2b, 0x65, 0x31, - 0x23, 0x30, 0x69, 0x35, 0x3c, 0xde, 0xe9, 0x44, 0x25, 0xf8, 0xfe, 0x88, 0x19, 0x91, 0xd9, 0xb5, - 0xf7, 0x16, 0x33, 0x22, 0x9b, 0x64, 0xf7, 0xe7, 0xd3, 0x1f, 0x16, 0xe0, 0x42, 0x66, 0xbd, 0xbe, - 0x63, 0x46, 0x74, 0xaf, 0x7d, 0x3c, 0x96, 0x71, 0xd9, 0x06, 0x6b, 0xc5, 0x13, 0x34, 0x58, 0x1b, - 0xe8, 0x97, 0xc3, 0x1c, 0xec, 0x23, 0x94, 0x43, 0xe6, 0x90, 0xbd, 0x4f, 0x42, 0x39, 0x64, 0xf6, - 0x2d, 0xe7, 0xf9, 0xf7, 0xe7, 0x85, 0x9c, 0x6f, 0x61, 0x0f, 0xc1, 0x2b, 0xf4, 0x9c, 0x61, 0xc0, - 0x48, 0x70, 0xcc, 0xa3, 0xfc, 0x8c, 0xe1, 0x65, 0x58, 0x41, 0xd1, 0x3c, 0x4c, 0x34, 0x3d, 0x9f, - 0x1e, 0x3e, 0xfb, 0x26, 0xe3, 0xa7, 0x22, 0xed, 0xac, 0x9a, 0x60, 0x9c, 0xc6, 0x47, 0x9e, 0x16, - 0xe6, 0xa1, 0x90, 0x9f, 0x76, 0x37, 0xb7, 0xb7, 0x73, 0xa6, 0xba, 0x54, 0x8d, 0x62, 0x46, 0xc8, - 0x87, 0x55, 0xed, 0xfd, 0x5f, 0xec, 0xff, 0xfd, 0x3f, 0x9a, 0xfd, 0xf6, 0x9f, 0x79, 0x15, 0xc6, - 0x1e, 0x5a, 0xe0, 0x6b, 0x7f, 0xad, 0x08, 0x8f, 0x77, 0xd9, 0xf6, 0xfc, 0xac, 0x37, 0xe6, 0x40, - 0x3b, 0xeb, 0x3b, 0xe6, 0xa1, 0x0a, 0xa7, 0x37, 0xdb, 0x8d, 0xc6, 0x3e, 0xb3, 0x09, 0x27, 0xae, - 0xc4, 0x10, 0x3c, 0xe5, 0x13, 0x32, 0xa3, 0xcd, 0x72, 0x06, 0x0e, 0xce, 0xac, 0x49, 0x19, 0x7a, - 0x7a, 0x93, 0xec, 0x2b, 0x52, 0x29, 0x86, 0x1e, 0xeb, 0x40, 0x6c, 0xe2, 0xa2, 0xeb, 0x30, 0xe5, - 0xec, 0x3a, 0x1e, 0x0f, 0x96, 0x29, 0x09, 0x70, 0x8e, 0x5e, 0xc9, 0xe9, 0xe6, 0xd3, 0x08, 0xb8, - 0xb3, 0x0e, 0x7a, 0x1d, 0x50, 0x20, 0xd2, 0x86, 0x5f, 0x27, 0xbe, 0xd0, 0x6a, 0xb1, 0xb9, 0x2b, - 0x26, 0x47, 0xc2, 0xed, 0x0e, 0x0c, 0x9c, 0x51, 0x2b, 0x15, 0x36, 0x61, 0x28, 0x3f, 0x6c, 0x42, - 0xf7, 0x73, 0xb1, 0x97, 0x20, 0xdb, 0xfe, 0x6f, 0x16, 0xbd, 0xbe, 0x38, 0x93, 0x6f, 0x46, 0xff, - 0x7a, 0x95, 0x19, 0x74, 0x71, 0x19, 0x9e, 0x16, 0xc1, 0xe0, 0x8c, 0x66, 0xd0, 0x95, 0x00, 0xb1, - 0x89, 0xcb, 0x17, 0x44, 0x94, 0x38, 0xce, 0x19, 0x2c, 0xbe, 0x08, 0x51, 0xa2, 0x30, 0xd0, 0x67, - 0x60, 0xd8, 0xf5, 0x76, 0xbd, 0x28, 0x08, 0xc5, 0x4a, 0x3f, 0xa2, 0xba, 0x20, 0x39, 0x07, 0x2b, - 0x9c, 0x0c, 0x96, 0xf4, 0xec, 0xef, 0x2f, 0xc0, 0x98, 0x6c, 0xf1, 0x8d, 0x76, 0x10, 0x3b, 0x27, - 0x70, 0x2d, 0x5f, 0x37, 0xae, 0xe5, 0x8f, 0x74, 0x8b, 0xd3, 0xc2, 0xba, 0x94, 0x7b, 0x1d, 0xdf, - 0x4e, 0x5d, 0xc7, 0x4f, 0xf5, 0x26, 0xd5, 0xfd, 0x1a, 0xfe, 0xe7, 0x16, 0x4c, 0x19, 0xf8, 0x27, - 0x70, 0x1b, 0x2c, 0x9b, 0xb7, 0xc1, 0x93, 0x3d, 0xbf, 0x21, 0xe7, 0x16, 0xf8, 0xee, 0x62, 0xaa, - 0xef, 0xec, 0xf4, 0x7f, 0x07, 0x06, 0xb6, 0x9d, 0xd0, 0xed, 0x16, 0x98, 0xba, 0xa3, 0xd2, 0xdc, - 0x0d, 0x27, 0x14, 0x6a, 0xbd, 0x67, 0x55, 0xd6, 0x5b, 0x27, 0xec, 0xad, 0xd2, 0x63, 0x4d, 0xa1, - 0x57, 0x60, 0x28, 0xaa, 0x07, 0x2d, 0x65, 0xc5, 0x7d, 0x91, 0x67, 0xc4, 0xa5, 0x25, 0x87, 0x07, - 0xb3, 0xc8, 0x6c, 0x8e, 0x16, 0x63, 0x81, 0x8f, 0xde, 0x84, 0x31, 0xf6, 0x4b, 0xd9, 0xd8, 0x14, - 0xf3, 0xd3, 0xa1, 0xd4, 0x74, 0x44, 0x6e, 0x80, 0x66, 0x14, 0x61, 0x93, 0xd4, 0xcc, 0x16, 0x94, - 0xd5, 0x67, 0x3d, 0x52, 0x7d, 0xdc, 0x7f, 0x2a, 0xc2, 0xa9, 0x8c, 0x35, 0x87, 0x22, 0x63, 0x26, - 0x9e, 0xef, 0x73, 0xa9, 0xbe, 0xc7, 0xb9, 0x88, 0xd8, 0x6b, 0xc8, 0x15, 0x6b, 0xab, 0xef, 0x46, - 0xef, 0x44, 0x24, 0xdd, 0x28, 0x2d, 0xea, 0xdd, 0x28, 0x6d, 0xec, 0xc4, 0x86, 0x9a, 0x36, 0xa4, - 0x7a, 0xfa, 0x48, 0xe7, 0xf4, 0x4f, 0x8a, 0x70, 0x3a, 0x2b, 0x74, 0x14, 0xfa, 0xf6, 0x54, 0x6a, - 0xac, 0x17, 0xfb, 0x0d, 0x3a, 0xc5, 0xf3, 0x65, 0x89, 0xcc, 0xf6, 0x73, 0x66, 0xb2, 0xac, 0x9e, - 0xc3, 0x2c, 0xda, 0x64, 0x4e, 0xe1, 0x21, 0x4f, 0x69, 0x26, 0x8f, 0x8f, 0x8f, 0xf7, 0xdd, 0x01, - 0x91, 0x0b, 0x2d, 0x4a, 0xe9, 0xef, 0x65, 0x71, 0x6f, 0xfd, 0xbd, 0x6c, 0x79, 0xc6, 0x83, 0x11, - 0xed, 0x6b, 0x1e, 0xe9, 0x8c, 0xef, 0xd0, 0xdb, 0x4a, 0xeb, 0xf7, 0x23, 0x9d, 0xf5, 0x1f, 0xb1, - 0x20, 0x65, 0x0d, 0xad, 0xc4, 0x62, 0x56, 0xae, 0x58, 0xec, 0x22, 0x0c, 0x84, 0x41, 0x83, 0xa4, - 0x33, 0x51, 0xe1, 0xa0, 0x41, 0x30, 0x83, 0x50, 0x8c, 0x38, 0x11, 0x76, 0x8c, 0xea, 0x0f, 0x39, - 0xf1, 0x44, 0xbb, 0x04, 0x83, 0x0d, 0xb2, 0x4b, 0x1a, 0xe9, 0x34, 0x0f, 0xb7, 0x68, 0x21, 0xe6, - 0x30, 0xfb, 0x17, 0x06, 0xe0, 0x7c, 0xd7, 0xb0, 0x0a, 0xf4, 0x39, 0xb4, 0xe5, 0xc4, 0x64, 0xcf, - 0xd9, 0x4f, 0xc7, 0x63, 0xbf, 0xce, 0x8b, 0xb1, 0x84, 0x33, 0x2f, 0x12, 0x1e, 0x55, 0x35, 0x25, - 0x44, 0x14, 0xc1, 0x54, 0x05, 0xd4, 0x14, 0x4a, 0x15, 0x8f, 0x43, 0x28, 0x75, 0x0d, 0x20, 0x8a, - 0x1a, 0xdc, 0xf0, 0xc5, 0x15, 0xee, 0x29, 0x49, 0xf4, 0xdd, 0xda, 0x2d, 0x01, 0xc1, 0x1a, 0x16, - 0xaa, 0xc0, 0x64, 0x2b, 0x0c, 0x62, 0x2e, 0x93, 0xad, 0x70, 0xdb, 0xb0, 0x41, 0xd3, 0xa3, 0xbd, - 0x9a, 0x82, 0xe3, 0x8e, 0x1a, 0xe8, 0x25, 0x18, 0x11, 0x5e, 0xee, 0xd5, 0x20, 0x68, 0x08, 0x31, - 0x90, 0x32, 0x97, 0xaa, 0x25, 0x20, 0xac, 0xe3, 0x69, 0xd5, 0x98, 0xa0, 0x77, 0x38, 0xb3, 0x1a, - 0x17, 0xf6, 0x6a, 0x78, 0xa9, 0x30, 0x72, 0xa5, 0xbe, 0xc2, 0xc8, 0x25, 0x82, 0xb1, 0x72, 0xdf, - 0xba, 0x2d, 0xe8, 0x29, 0x4a, 0xfa, 0xb9, 0x01, 0x38, 0x25, 0x16, 0xce, 0xa3, 0x5e, 0x2e, 0x77, - 0x3a, 0x97, 0xcb, 0x71, 0x88, 0xce, 0x3e, 0x58, 0x33, 0x27, 0xbd, 0x66, 0x7e, 0xc0, 0x02, 0x93, - 0xbd, 0x42, 0x7f, 0x29, 0x37, 0xa1, 0xc5, 0x4b, 0xb9, 0xec, 0x9a, 0x2b, 0x2f, 0x90, 0xf7, 0x98, - 0xda, 0xc2, 0xfe, 0xaf, 0x16, 0x3c, 0xd9, 0x93, 0x22, 0x5a, 0x82, 0x32, 0xe3, 0x01, 0xb5, 0xd7, - 0xd9, 0x53, 0xca, 0x76, 0x54, 0x02, 0x72, 0x58, 0xd2, 0xa4, 0x26, 0x5a, 0xea, 0xc8, 0x1c, 0xf2, - 0x74, 0x46, 0xe6, 0x90, 0x33, 0xc6, 0xf0, 0x3c, 0x64, 0xea, 0x90, 0x5f, 0x2e, 0xc2, 0x10, 0x5f, - 0xf1, 0x27, 0xf0, 0x0c, 0x5b, 0x16, 0x72, 0xdb, 0x2e, 0x71, 0xea, 0x78, 0x5f, 0xe6, 0x2a, 0x4e, - 0xec, 0x70, 0x36, 0x41, 0xdd, 0x56, 0x89, 0x84, 0x17, 0x7d, 0x0e, 0x20, 0x8a, 0x43, 0xcf, 0xdf, - 0xa2, 0x65, 0x22, 0x82, 0xe1, 0x47, 0xbb, 0x50, 0xab, 0x29, 0x64, 0x4e, 0x33, 0xd9, 0xb9, 0x0a, - 0x80, 0x35, 0x8a, 0x68, 0xce, 0xb8, 0x2f, 0x67, 0x52, 0x82, 0x4f, 0xe0, 0x54, 0x93, 0xdb, 0x73, - 0xe6, 0x65, 0x28, 0x2b, 0xe2, 0xbd, 0xa4, 0x38, 0xa3, 0x3a, 0x73, 0xf1, 0x29, 0x98, 0x48, 0xf5, - 0xed, 0x48, 0x42, 0xa0, 0x5f, 0xb4, 0x60, 0x82, 0x77, 0x66, 0xc9, 0xdf, 0x15, 0x67, 0xea, 0xbb, - 0x70, 0xba, 0x91, 0x71, 0xb6, 0x89, 0x19, 0xed, 0xff, 0x2c, 0x54, 0x42, 0x9f, 0x2c, 0x28, 0xce, - 0x6c, 0x03, 0x5d, 0xa1, 0xeb, 0x96, 0x9e, 0x5d, 0x4e, 0x43, 0x38, 0x1b, 0x8e, 0xf2, 0x35, 0xcb, - 0xcb, 0xb0, 0x82, 0xda, 0xbf, 0x65, 0xc1, 0x14, 0xef, 0xf9, 0x4d, 0xb2, 0xaf, 0x76, 0xf8, 0xd7, - 0xb3, 0xef, 0x22, 0x99, 0x4f, 0x21, 0x27, 0x99, 0x8f, 0xfe, 0x69, 0xc5, 0xae, 0x9f, 0xf6, 0x33, - 0x16, 0x88, 0x15, 0x72, 0x02, 0x4f, 0xf9, 0x6f, 0x36, 0x9f, 0xf2, 0x33, 0xf9, 0x9b, 0x20, 0xe7, - 0x0d, 0xff, 0x67, 0x16, 0x4c, 0x72, 0x84, 0x44, 0xe7, 0xfc, 0x75, 0x9d, 0x87, 0x7e, 0xb2, 0x72, - 0xaa, 0x54, 0xfd, 0xd9, 0x1f, 0x65, 0x4c, 0xd6, 0x40, 0xd7, 0xc9, 0x72, 0xe5, 0x06, 0x3a, 0x42, - 0x46, 0xda, 0x23, 0x87, 0xba, 0xb7, 0xff, 0xc0, 0x02, 0xc4, 0x9b, 0x31, 0xd8, 0x1f, 0xca, 0x54, - 0xb0, 0x52, 0xed, 0xba, 0x48, 0x8e, 0x26, 0x05, 0xc1, 0x1a, 0xd6, 0xb1, 0x0c, 0x4f, 0xca, 0x70, - 0xa0, 0xd8, 0xdb, 0x70, 0xe0, 0x08, 0x23, 0xfa, 0xfb, 0x83, 0x90, 0xf6, 0x00, 0x41, 0x77, 0x61, - 0xb4, 0xee, 0xb4, 0x9c, 0x0d, 0xaf, 0xe1, 0xc5, 0x1e, 0x89, 0xba, 0x59, 0x1c, 0x2d, 0x6a, 0x78, - 0x42, 0xd5, 0xab, 0x95, 0x60, 0x83, 0x0e, 0x9a, 0x03, 0x68, 0x85, 0xde, 0xae, 0xd7, 0x20, 0x5b, - 0x4c, 0xe2, 0xc0, 0xdc, 0x9b, 0xb9, 0x19, 0x8d, 0x2c, 0xc5, 0x1a, 0x46, 0x86, 0xa7, 0x6a, 0xf1, - 0x11, 0x7b, 0xaa, 0xc2, 0x89, 0x79, 0xaa, 0x0e, 0x1c, 0xc9, 0x53, 0xb5, 0x74, 0x64, 0x4f, 0xd5, - 0xc1, 0xbe, 0x3c, 0x55, 0x31, 0x9c, 0x95, 0x1c, 0x1c, 0xfd, 0xbf, 0xec, 0x35, 0x88, 0x60, 0xdb, - 0xb9, 0x4f, 0xf6, 0xcc, 0x83, 0x83, 0xd9, 0xb3, 0x38, 0x13, 0x03, 0xe7, 0xd4, 0x44, 0x9f, 0x86, - 0x69, 0xa7, 0xd1, 0x08, 0xf6, 0xd4, 0xa4, 0x2e, 0x45, 0x75, 0xa7, 0xc1, 0x45, 0xf9, 0xc3, 0x8c, - 0xea, 0x13, 0x0f, 0x0e, 0x66, 0xa7, 0xe7, 0x73, 0x70, 0x70, 0x6e, 0x6d, 0xf4, 0x49, 0x28, 0xb7, - 0xc2, 0xa0, 0xbe, 0xaa, 0xb9, 0xa9, 0x5d, 0xa0, 0x03, 0x58, 0x95, 0x85, 0x87, 0x07, 0xb3, 0x63, - 0xea, 0x0f, 0xbb, 0xf0, 0x93, 0x0a, 0xf6, 0x0e, 0x9c, 0xaa, 0x91, 0xd0, 0x63, 0x89, 0x7b, 0xdd, - 0xe4, 0xfc, 0x58, 0x87, 0x72, 0x98, 0x3a, 0x31, 0xfb, 0x8a, 0xed, 0xa6, 0xc5, 0x04, 0x97, 0x27, - 0x64, 0x42, 0xc8, 0xfe, 0x3f, 0x16, 0x0c, 0x0b, 0x8f, 0x8c, 0x13, 0x60, 0xd4, 0xe6, 0x0d, 0x79, - 0xf9, 0x6c, 0xf6, 0xad, 0xc2, 0x3a, 0x93, 0x2b, 0x29, 0x5f, 0x49, 0x49, 0xca, 0x9f, 0xec, 0x46, - 0xa4, 0xbb, 0x8c, 0xfc, 0xef, 0x14, 0x61, 0xdc, 0x74, 0xdd, 0x3b, 0x81, 0x21, 0x58, 0x83, 0xe1, - 0x48, 0xf8, 0xa6, 0x15, 0xf2, 0x2d, 0xb2, 0xd3, 0x93, 0x98, 0x58, 0x6b, 0x09, 0x6f, 0x34, 0x49, - 0x24, 0xd3, 0xe9, 0xad, 0xf8, 0x08, 0x9d, 0xde, 0x7a, 0x79, 0x4f, 0x0e, 0x1c, 0x87, 0xf7, 0xa4, - 0xfd, 0x15, 0x76, 0xb3, 0xe9, 0xe5, 0x27, 0xc0, 0xf4, 0x5c, 0x37, 0xef, 0x40, 0xbb, 0xcb, 0xca, - 0x12, 0x9d, 0xca, 0x61, 0x7e, 0x7e, 0xde, 0x82, 0xf3, 0x19, 0x5f, 0xa5, 0x71, 0x42, 0xcf, 0x42, - 0xc9, 0x69, 0xbb, 0x9e, 0xda, 0xcb, 0x9a, 0xd6, 0x6c, 0x5e, 0x94, 0x63, 0x85, 0x81, 0x16, 0x61, - 0x8a, 0xdc, 0x6f, 0x79, 0x5c, 0x61, 0xa8, 0x9b, 0x54, 0x16, 0x79, 0xbc, 0xeb, 0xa5, 0x34, 0x10, - 0x77, 0xe2, 0xab, 0x60, 0x0f, 0xc5, 0xdc, 0x60, 0x0f, 0xff, 0xc8, 0x82, 0x11, 0xe5, 0x9d, 0xf5, - 0xc8, 0x47, 0xfb, 0x5b, 0xcc, 0xd1, 0x7e, 0xbc, 0xcb, 0x68, 0xe7, 0x0c, 0xf3, 0xdf, 0x2b, 0xa8, - 0xfe, 0x56, 0x83, 0x30, 0xee, 0x83, 0xc3, 0x7a, 0x05, 0x4a, 0xad, 0x30, 0x88, 0x83, 0x7a, 0xd0, - 0x10, 0x0c, 0xd6, 0x13, 0x49, 0x2c, 0x12, 0x5e, 0x7e, 0xa8, 0xfd, 0xc6, 0x0a, 0x9b, 0x8d, 0x5e, - 0x10, 0xc6, 0x82, 0xa9, 0x49, 0x46, 0x2f, 0x08, 0x63, 0xcc, 0x20, 0xc8, 0x05, 0x88, 0x9d, 0x70, - 0x8b, 0xc4, 0xb4, 0x4c, 0xc4, 0x3e, 0xca, 0x3f, 0x3c, 0xda, 0xb1, 0xd7, 0x98, 0xf3, 0xfc, 0x38, - 0x8a, 0xc3, 0xb9, 0x15, 0x3f, 0xbe, 0x1d, 0xf2, 0xf7, 0x9a, 0x16, 0x5c, 0x44, 0xd1, 0xc2, 0x1a, - 0x5d, 0xe9, 0x56, 0xcc, 0xda, 0x18, 0x34, 0xf5, 0xef, 0x6b, 0xa2, 0x1c, 0x2b, 0x0c, 0xfb, 0x65, - 0x76, 0x95, 0xb0, 0x01, 0x3a, 0x5a, 0xdc, 0x8f, 0xaf, 0x96, 0xd4, 0xd0, 0x32, 0xe5, 0x5b, 0x45, - 0x8f, 0x2e, 0xd2, 0xfd, 0xe4, 0xa6, 0x0d, 0xeb, 0x2e, 0x46, 0x49, 0x08, 0x12, 0xf4, 0xad, 0x1d, - 0x36, 0x15, 0xcf, 0xf5, 0xb8, 0x02, 0x8e, 0x60, 0x45, 0xc1, 0x62, 0xf0, 0xb3, 0x08, 0xe5, 0x2b, - 0x55, 0xb1, 0xc8, 0xb5, 0x18, 0xfc, 0x02, 0x80, 0x13, 0x1c, 0x74, 0x55, 0xbc, 0xc6, 0x07, 0x8c, - 0xcc, 0x93, 0xf2, 0x35, 0x2e, 0x3f, 0x5f, 0x13, 0x66, 0x3f, 0x0f, 0x23, 0x2a, 0x03, 0x65, 0x95, - 0x27, 0x36, 0x14, 0x91, 0xa0, 0x96, 0x92, 0x62, 0xac, 0xe3, 0xa0, 0x75, 0x98, 0x88, 0xb8, 0xa8, - 0x47, 0x05, 0xfc, 0xe4, 0x22, 0xb3, 0x8f, 0x4a, 0x43, 0x94, 0x9a, 0x09, 0x3e, 0x64, 0x45, 0xfc, - 0xe8, 0x90, 0xae, 0xbc, 0x69, 0x12, 0xe8, 0x35, 0x18, 0x6f, 0x04, 0x8e, 0xbb, 0xe0, 0x34, 0x1c, - 0xbf, 0xce, 0xbe, 0xb7, 0x64, 0x26, 0x32, 0xbb, 0x65, 0x40, 0x71, 0x0a, 0x9b, 0x72, 0x3e, 0x7a, - 0x89, 0x08, 0x52, 0xeb, 0xf8, 0x5b, 0x24, 0x12, 0xf9, 0x04, 0x19, 0xe7, 0x73, 0x2b, 0x07, 0x07, - 0xe7, 0xd6, 0x46, 0xaf, 0xc0, 0xa8, 0xfc, 0x7c, 0xcd, 0xf3, 0x3d, 0xb1, 0xbd, 0xd7, 0x60, 0xd8, - 0xc0, 0x44, 0x7b, 0x70, 0x46, 0xfe, 0x5f, 0x0f, 0x9d, 0xcd, 0x4d, 0xaf, 0x2e, 0xdc, 0x41, 0xb9, - 0x63, 0xdc, 0xbc, 0xf4, 0xde, 0x5a, 0xca, 0x42, 0x3a, 0x3c, 0x98, 0xbd, 0x28, 0x46, 0x2d, 0x13, - 0xce, 0x26, 0x31, 0x9b, 0x3e, 0x5a, 0x85, 0x53, 0xdb, 0xc4, 0x69, 0xc4, 0xdb, 0x8b, 0xdb, 0xa4, - 0xbe, 0x23, 0x37, 0x11, 0xf3, 0xa7, 0xd7, 0x2c, 0xd6, 0x6f, 0x74, 0xa2, 0xe0, 0xac, 0x7a, 0xe8, - 0x2d, 0x98, 0x6e, 0xb5, 0x37, 0x1a, 0x5e, 0xb4, 0xbd, 0x16, 0xc4, 0xcc, 0x1a, 0x45, 0x25, 0xb4, - 0x14, 0x8e, 0xf7, 0x2a, 0x62, 0x41, 0x35, 0x07, 0x0f, 0xe7, 0x52, 0x40, 0xef, 0xc2, 0x99, 0xd4, - 0x62, 0x10, 0xae, 0xc7, 0xe3, 0xf9, 0x21, 0xbf, 0x6b, 0x59, 0x15, 0x84, 0x17, 0x7f, 0x16, 0x08, - 0x67, 0x37, 0xf1, 0xde, 0xec, 0x8a, 0xde, 0xa1, 0x95, 0x35, 0xa6, 0x0c, 0x7d, 0x1e, 0x46, 0xf5, - 0x55, 0x24, 0x2e, 0x98, 0xcb, 0xd9, 0x3c, 0x8b, 0xb6, 0xda, 0x38, 0x4b, 0xa7, 0x56, 0x94, 0x0e, - 0xc3, 0x06, 0x45, 0x9b, 0x40, 0xf6, 0xf7, 0xa1, 0x5b, 0x50, 0xaa, 0x37, 0x3c, 0xe2, 0xc7, 0x2b, - 0xd5, 0x6e, 0x21, 0x85, 0x16, 0x05, 0x8e, 0x18, 0x30, 0x11, 0x23, 0x99, 0x97, 0x61, 0x45, 0xc1, - 0xfe, 0xd5, 0x02, 0xcc, 0xf6, 0x08, 0xb8, 0x9d, 0x12, 0x7f, 0x5b, 0x7d, 0x89, 0xbf, 0xe7, 0x65, - 0x7a, 0xce, 0xb5, 0x94, 0x4c, 0x20, 0x95, 0x7a, 0x33, 0x91, 0x0c, 0xa4, 0xf1, 0xfb, 0x36, 0x47, - 0xd6, 0x25, 0xe8, 0x03, 0x3d, 0x0d, 0xea, 0x0d, 0xcd, 0xd9, 0x60, 0xff, 0x0f, 0x91, 0x5c, 0x2d, - 0x88, 0xfd, 0x95, 0x02, 0x9c, 0x51, 0x43, 0xf8, 0x8d, 0x3b, 0x70, 0x77, 0x3a, 0x07, 0xee, 0x18, - 0x74, 0x48, 0xf6, 0x6d, 0x18, 0xe2, 0x31, 0x92, 0xfa, 0x60, 0x80, 0x2e, 0x99, 0x41, 0xfe, 0xd4, - 0x35, 0x6d, 0x04, 0xfa, 0xfb, 0x5e, 0x0b, 0x26, 0xd6, 0x17, 0xab, 0xb5, 0xa0, 0xbe, 0x43, 0xe2, - 0x79, 0xce, 0xb0, 0x62, 0xc1, 0xff, 0x58, 0x0f, 0xc9, 0xd7, 0x64, 0x71, 0x4c, 0x17, 0x61, 0x60, - 0x3b, 0x88, 0xe2, 0xb4, 0x82, 0xf9, 0x46, 0x10, 0xc5, 0x98, 0x41, 0xec, 0xdf, 0xb6, 0x60, 0x90, - 0x65, 0xa4, 0xee, 0x95, 0x13, 0xbd, 0x9f, 0xef, 0x42, 0x2f, 0xc1, 0x10, 0xd9, 0xdc, 0x24, 0xf5, - 0x58, 0xcc, 0xaa, 0xf4, 0x08, 0x1e, 0x5a, 0x62, 0xa5, 0xf4, 0xd2, 0x67, 0x8d, 0xf1, 0xbf, 0x58, - 0x20, 0xa3, 0x7b, 0x50, 0x8e, 0xbd, 0x26, 0x99, 0x77, 0x5d, 0xa1, 0xa2, 0x7b, 0x08, 0xaf, 0xe6, - 0x75, 0x49, 0x00, 0x27, 0xb4, 0xec, 0x2f, 0x15, 0x00, 0x92, 0x08, 0x19, 0xbd, 0x3e, 0x71, 0xa1, - 0x43, 0x79, 0x73, 0x39, 0x43, 0x79, 0x83, 0x12, 0x82, 0x19, 0x9a, 0x1b, 0x35, 0x4c, 0xc5, 0xbe, - 0x86, 0x69, 0xe0, 0x28, 0xc3, 0xb4, 0x08, 0x53, 0x49, 0x84, 0x0f, 0x33, 0xc0, 0x11, 0x7b, 0xa4, - 0xac, 0xa7, 0x81, 0xb8, 0x13, 0xdf, 0x26, 0x70, 0x51, 0x05, 0x3a, 0x10, 0x77, 0x0d, 0xb3, 0x00, - 0x3d, 0x42, 0x7a, 0xfc, 0x44, 0x3b, 0x55, 0xc8, 0xd5, 0x4e, 0xfd, 0xb8, 0x05, 0xa7, 0xd3, 0xed, - 0x30, 0x97, 0xbc, 0x2f, 0x5a, 0x70, 0x86, 0xe9, 0xe8, 0x58, 0xab, 0x9d, 0x1a, 0xc1, 0x17, 0xbb, - 0x06, 0x6f, 0xc8, 0xe9, 0x71, 0xe2, 0x7a, 0xbe, 0x9a, 0x45, 0x1a, 0x67, 0xb7, 0x68, 0xff, 0x97, - 0x02, 0x4c, 0xe7, 0x45, 0x7d, 0x60, 0x06, 0xe2, 0xce, 0xfd, 0xda, 0x0e, 0xd9, 0x13, 0x66, 0xb8, - 0x89, 0x81, 0x38, 0x2f, 0xc6, 0x12, 0x9e, 0x8e, 0xa1, 0x5c, 0xe8, 0x2f, 0x86, 0x32, 0xda, 0x86, - 0xa9, 0xbd, 0x6d, 0xe2, 0xdf, 0xf1, 0x23, 0x27, 0xf6, 0xa2, 0x4d, 0x8f, 0xe5, 0x36, 0xe7, 0xeb, - 0xe6, 0x13, 0xd2, 0x58, 0xf6, 0x5e, 0x1a, 0xe1, 0xf0, 0x60, 0xf6, 0xbc, 0x51, 0x90, 0x74, 0x99, - 0x1f, 0x24, 0xb8, 0x93, 0x68, 0x67, 0x08, 0xea, 0x81, 0x47, 0x18, 0x82, 0xda, 0xfe, 0xa2, 0x05, - 0xe7, 0x72, 0x53, 0xc4, 0xa1, 0x2b, 0x50, 0x72, 0x5a, 0x1e, 0x17, 0x66, 0x8a, 0x63, 0x94, 0x3d, - 0xca, 0xab, 0x2b, 0x5c, 0x94, 0xa9, 0xa0, 0x2a, 0x75, 0x6d, 0x21, 0x37, 0x75, 0x6d, 0xcf, 0x4c, - 0xb4, 0xf6, 0xf7, 0x58, 0x20, 0x9c, 0xdb, 0xfa, 0x38, 0xbb, 0xdf, 0x94, 0x99, 0xbf, 0x8d, 0x34, - 0x15, 0x17, 0xf3, 0xbd, 0xfd, 0x44, 0x72, 0x0a, 0xc5, 0x2b, 0x19, 0x29, 0x29, 0x0c, 0x5a, 0xb6, - 0x0b, 0x02, 0x5a, 0x21, 0x4c, 0x14, 0xd8, 0xbb, 0x37, 0xd7, 0x00, 0x5c, 0x86, 0xab, 0xe5, 0xff, - 0x55, 0x37, 0x73, 0x45, 0x41, 0xb0, 0x86, 0x65, 0xff, 0x87, 0x02, 0x8c, 0xc8, 0xb4, 0x08, 0x6d, - 0xbf, 0x9f, 0x07, 0xfb, 0x91, 0xf2, 0xa4, 0xb1, 0x84, 0xd9, 0x94, 0x70, 0x35, 0x91, 0x73, 0x24, - 0x09, 0xb3, 0x25, 0x00, 0x27, 0x38, 0x74, 0x17, 0x45, 0xed, 0x0d, 0x86, 0x9e, 0x72, 0xc5, 0xaa, - 0xf1, 0x62, 0x2c, 0xe1, 0xe8, 0xd3, 0x30, 0xc9, 0xeb, 0x85, 0x41, 0xcb, 0xd9, 0xe2, 0x52, 0xe2, - 0x41, 0xe5, 0x43, 0x3d, 0xb9, 0x9a, 0x82, 0x1d, 0x1e, 0xcc, 0x9e, 0x4e, 0x97, 0x31, 0xf5, 0x47, - 0x07, 0x15, 0x66, 0x52, 0xc1, 0x1b, 0xa1, 0xbb, 0xbf, 0xc3, 0x12, 0x23, 0x01, 0x61, 0x1d, 0xcf, - 0xfe, 0x3c, 0xa0, 0xce, 0x04, 0x11, 0xe8, 0x75, 0x6e, 0x47, 0xe7, 0x85, 0xc4, 0xed, 0xa6, 0x0e, - 0xd1, 0x3d, 0x85, 0xa5, 0x17, 0x05, 0xaf, 0x85, 0x55, 0x7d, 0xfb, 0xaf, 0x17, 0x61, 0x32, 0xed, - 0x37, 0x8a, 0x6e, 0xc0, 0x10, 0x67, 0x3d, 0x04, 0xf9, 0x2e, 0xda, 0x76, 0xcd, 0xdb, 0x94, 0x1d, - 0xc2, 0x82, 0x7b, 0x11, 0xf5, 0xd1, 0x5b, 0x30, 0xe2, 0x06, 0x7b, 0xfe, 0x9e, 0x13, 0xba, 0xf3, - 0xd5, 0x15, 0xb1, 0x9c, 0x33, 0x5f, 0x30, 0x95, 0x04, 0x4d, 0xf7, 0x60, 0x65, 0x9a, 0xa5, 0x04, - 0x84, 0x75, 0x72, 0x68, 0x9d, 0xc5, 0xb3, 0xdd, 0xf4, 0xb6, 0x56, 0x9d, 0x56, 0x37, 0xa3, 0xea, - 0x45, 0x89, 0xa4, 0x51, 0x1e, 0x13, 0x41, 0x6f, 0x39, 0x00, 0x27, 0x84, 0xd0, 0xb7, 0xc3, 0xa9, - 0x28, 0x47, 0xe8, 0x99, 0x97, 0x2f, 0xa8, 0x9b, 0x1c, 0x70, 0xe1, 0x31, 0xfa, 0xb6, 0xcc, 0x12, - 0x8f, 0x66, 0x35, 0x63, 0xff, 0xda, 0x29, 0x30, 0x36, 0xb1, 0x91, 0x3e, 0xce, 0x3a, 0xa6, 0xf4, - 0x71, 0x18, 0x4a, 0xa4, 0xd9, 0x8a, 0xf7, 0x2b, 0x5e, 0xd8, 0x2d, 0xff, 0xe8, 0x92, 0xc0, 0xe9, - 0xa4, 0x29, 0x21, 0x58, 0xd1, 0xc9, 0xce, 0xf1, 0x57, 0xfc, 0x3a, 0xe6, 0xf8, 0x1b, 0x38, 0xc1, - 0x1c, 0x7f, 0x6b, 0x30, 0xbc, 0xe5, 0xc5, 0x98, 0xb4, 0x02, 0xc1, 0xf4, 0x67, 0xae, 0xc3, 0xeb, - 0x1c, 0xa5, 0x33, 0x9b, 0x94, 0x00, 0x60, 0x49, 0x04, 0xbd, 0xae, 0x76, 0xe0, 0x50, 0xfe, 0x9b, - 0xb9, 0x53, 0x2d, 0x9c, 0xb9, 0x07, 0x45, 0x26, 0xbf, 0xe1, 0x87, 0xcd, 0xe4, 0xb7, 0x2c, 0xf3, - 0xef, 0x95, 0xf2, 0x3d, 0x20, 0x58, 0x7a, 0xbd, 0x1e, 0x59, 0xf7, 0xee, 0xea, 0x39, 0x0b, 0xcb, - 0xf9, 0x27, 0x81, 0x4a, 0x47, 0xd8, 0x67, 0xa6, 0xc2, 0xef, 0xb1, 0xe0, 0x4c, 0x2b, 0x2b, 0x7d, - 0xa7, 0xd0, 0xa0, 0xbe, 0xd4, 0x77, 0x7e, 0x52, 0xa3, 0x41, 0x26, 0x3c, 0xc9, 0x44, 0xc3, 0xd9, - 0xcd, 0xd1, 0x81, 0x0e, 0x37, 0x5c, 0x91, 0x6a, 0xef, 0x52, 0x4e, 0xca, 0xc3, 0x2e, 0x89, 0x0e, - 0xd7, 0x33, 0xd2, 0xeb, 0x7d, 0x38, 0x2f, 0xbd, 0x5e, 0xdf, 0x49, 0xf5, 0x5e, 0x57, 0xc9, 0x0e, - 0xc7, 0xf2, 0x97, 0x12, 0x4f, 0x65, 0xd8, 0x33, 0xc5, 0xe1, 0xeb, 0x2a, 0xc5, 0x61, 0x97, 0xd8, - 0x8e, 0x3c, 0x81, 0x61, 0xcf, 0xc4, 0x86, 0x5a, 0x72, 0xc2, 0x89, 0xe3, 0x49, 0x4e, 0x68, 0x5c, - 0x35, 0x3c, 0x3f, 0xde, 0x33, 0x3d, 0xae, 0x1a, 0x83, 0x6e, 0xf7, 0xcb, 0x86, 0x27, 0x62, 0x9c, - 0x7a, 0xa8, 0x44, 0x8c, 0x77, 0xf5, 0xc4, 0x86, 0xa8, 0x47, 0xe6, 0x3e, 0x8a, 0xd4, 0x67, 0x3a, - 0xc3, 0xbb, 0xfa, 0x05, 0x78, 0x2a, 0x9f, 0xae, 0xba, 0xe7, 0x3a, 0xe9, 0x66, 0x5e, 0x81, 0x1d, - 0x69, 0x12, 0x4f, 0x9f, 0x4c, 0x9a, 0xc4, 0x33, 0xc7, 0x9e, 0x26, 0xf1, 0xec, 0x09, 0xa4, 0x49, - 0x7c, 0xec, 0x04, 0xd3, 0x24, 0xde, 0x65, 0x66, 0x07, 0x3c, 0x44, 0x88, 0x88, 0x45, 0x99, 0x1d, - 0xf7, 0x30, 0x2b, 0x8e, 0x08, 0xff, 0x38, 0x05, 0xc2, 0x09, 0xa9, 0x8c, 0xf4, 0x8b, 0xd3, 0x8f, - 0x20, 0xfd, 0xe2, 0x5a, 0x92, 0x7e, 0xf1, 0x5c, 0xfe, 0x54, 0x67, 0x98, 0x7b, 0xe7, 0x24, 0x5d, - 0xbc, 0xab, 0x27, 0x4b, 0x7c, 0xbc, 0x8b, 0x78, 0x3c, 0x4b, 0xf0, 0xd8, 0x25, 0x45, 0xe2, 0x6b, - 0x3c, 0x45, 0xe2, 0x13, 0xf9, 0x27, 0x79, 0xfa, 0xba, 0x33, 0x13, 0x23, 0x7e, 0x5f, 0x01, 0x2e, - 0x74, 0xdf, 0x17, 0x89, 0xd4, 0xb3, 0x9a, 0x68, 0xe9, 0x52, 0x52, 0x4f, 0xfe, 0xb6, 0x4a, 0xb0, - 0xfa, 0x8e, 0x1e, 0x75, 0x1d, 0xa6, 0x94, 0x3d, 0x77, 0xc3, 0xab, 0xef, 0x6b, 0xb9, 0xe0, 0x95, - 0x0f, 0x6c, 0x2d, 0x8d, 0x80, 0x3b, 0xeb, 0xa0, 0x79, 0x98, 0x30, 0x0a, 0x57, 0x2a, 0xe2, 0x0d, - 0xa5, 0xc4, 0xac, 0x35, 0x13, 0x8c, 0xd3, 0xf8, 0xf6, 0x4f, 0x5b, 0xf0, 0x58, 0x4e, 0x06, 0xa2, - 0xbe, 0x83, 0x23, 0x6d, 0xc2, 0x44, 0xcb, 0xac, 0xda, 0x23, 0x86, 0x9a, 0x91, 0xe7, 0x48, 0xf5, - 0x35, 0x05, 0xc0, 0x69, 0xa2, 0xf6, 0x9f, 0x5a, 0x70, 0xbe, 0xab, 0x69, 0x15, 0xc2, 0x70, 0x76, - 0xab, 0x19, 0x39, 0x8b, 0x21, 0x71, 0x89, 0x1f, 0x7b, 0x4e, 0xa3, 0xd6, 0x22, 0x75, 0x4d, 0x6e, - 0xcd, 0x6c, 0x94, 0xae, 0xaf, 0xd6, 0xe6, 0x3b, 0x31, 0x70, 0x4e, 0x4d, 0xb4, 0x0c, 0xa8, 0x13, - 0x22, 0x66, 0x98, 0xc5, 0x59, 0xed, 0xa4, 0x87, 0x33, 0x6a, 0xa0, 0x97, 0x61, 0x4c, 0x99, 0x6c, - 0x69, 0x33, 0xce, 0x0e, 0x60, 0xac, 0x03, 0xb0, 0x89, 0xb7, 0x70, 0xe5, 0x37, 0x7e, 0xf7, 0xc2, - 0x87, 0x7e, 0xf3, 0x77, 0x2f, 0x7c, 0xe8, 0xb7, 0x7e, 0xf7, 0xc2, 0x87, 0xbe, 0xf3, 0xc1, 0x05, - 0xeb, 0x37, 0x1e, 0x5c, 0xb0, 0x7e, 0xf3, 0xc1, 0x05, 0xeb, 0xb7, 0x1e, 0x5c, 0xb0, 0x7e, 0xe7, - 0xc1, 0x05, 0xeb, 0x4b, 0xbf, 0x77, 0xe1, 0x43, 0x6f, 0x16, 0x76, 0x9f, 0xff, 0xff, 0x01, 0x00, - 0x00, 0xff, 0xff, 0xee, 0x7c, 0xe3, 0x20, 0x5f, 0xf9, 0x00, 0x00, + // 13495 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0xbd, 0x6b, 0x90, 0x24, 0x57, + 0x5a, 0x18, 0xba, 0x59, 0xd5, 0x8f, 0xaa, 0xaf, 0xdf, 0x67, 0x1e, 0xea, 0x69, 0x69, 0xa6, 0x47, + 0xa9, 0xdd, 0xd1, 0x68, 0x25, 0xf5, 0xac, 0x5e, 0x2b, 0xb1, 0xd2, 0x0a, 0xba, 0xbb, 0xba, 0x67, + 0x4a, 0x33, 0xdd, 0x53, 0x3a, 0xd5, 0x33, 0xb3, 0x2b, 0xb4, 0xcb, 0x66, 0x57, 0x9e, 0xee, 0x4e, + 0x75, 0x55, 0x66, 0x29, 0x33, 0xab, 0x67, 0x5a, 0x17, 0xe2, 0x72, 0x97, 0xe7, 0x5e, 0xe0, 0xc6, + 0xc6, 0x35, 0xe1, 0x07, 0x10, 0x38, 0x02, 0xe3, 0x00, 0x0c, 0x76, 0x18, 0x2f, 0x06, 0xcc, 0x62, + 0x1b, 0x83, 0xed, 0xc0, 0xfe, 0x81, 0xb1, 0xc3, 0x8e, 0x25, 0x82, 0x70, 0x1b, 0x06, 0x87, 0x09, + 0x7e, 0x18, 0x08, 0xc3, 0x1f, 0xb7, 0x09, 0xe3, 0x38, 0xcf, 0x3c, 0x27, 0x2b, 0xb3, 0xaa, 0x7a, + 0xd4, 0xd3, 0x2b, 0x36, 0xf4, 0xaf, 0xea, 0x7c, 0xdf, 0xf9, 0xce, 0xc9, 0xf3, 0xfc, 0xce, 0xf7, + 0x84, 0x57, 0x77, 0x5f, 0x89, 0x16, 0xbc, 0xe0, 0xca, 0x6e, 0x67, 0x93, 0x84, 0x3e, 0x89, 0x49, + 0x74, 0x65, 0x8f, 0xf8, 0x6e, 0x10, 0x5e, 0x11, 0x00, 0xa7, 0xed, 0x5d, 0x69, 0x04, 0x21, 0xb9, + 0xb2, 0xf7, 0xdc, 0x95, 0x6d, 0xe2, 0x93, 0xd0, 0x89, 0x89, 0xbb, 0xd0, 0x0e, 0x83, 0x38, 0x40, + 0x88, 0xe3, 0x2c, 0x38, 0x6d, 0x6f, 0x81, 0xe2, 0x2c, 0xec, 0x3d, 0x37, 0xf7, 0xec, 0xb6, 0x17, + 0xef, 0x74, 0x36, 0x17, 0x1a, 0x41, 0xeb, 0xca, 0x76, 0xb0, 0x1d, 0x5c, 0x61, 0xa8, 0x9b, 0x9d, + 0x2d, 0xf6, 0x8f, 0xfd, 0x61, 0xbf, 0x38, 0x89, 0xb9, 0x17, 0x93, 0x66, 0x5a, 0x4e, 0x63, 0xc7, + 0xf3, 0x49, 0xb8, 0x7f, 0xa5, 0xbd, 0xbb, 0xcd, 0xda, 0x0d, 0x49, 0x14, 0x74, 0xc2, 0x06, 0x49, + 0x37, 0xdc, 0xb3, 0x56, 0x74, 0xa5, 0x45, 0x62, 0x27, 0xa3, 0xbb, 0x73, 0x57, 0xf2, 0x6a, 0x85, + 0x1d, 0x3f, 0xf6, 0x5a, 0xdd, 0xcd, 0x7c, 0xb2, 0x5f, 0x85, 0xa8, 0xb1, 0x43, 0x5a, 0x4e, 0x57, + 0xbd, 0x17, 0xf2, 0xea, 0x75, 0x62, 0xaf, 0x79, 0xc5, 0xf3, 0xe3, 0x28, 0x0e, 0xd3, 0x95, 0xec, + 0xaf, 0x59, 0x70, 0x71, 0xf1, 0x4e, 0x7d, 0xa5, 0xe9, 0x44, 0xb1, 0xd7, 0x58, 0x6a, 0x06, 0x8d, + 0xdd, 0x7a, 0x1c, 0x84, 0xe4, 0x76, 0xd0, 0xec, 0xb4, 0x48, 0x9d, 0x0d, 0x04, 0x7a, 0x06, 0x4a, + 0x7b, 0xec, 0x7f, 0xb5, 0x32, 0x6b, 0x5d, 0xb4, 0x2e, 0x97, 0x97, 0xa6, 0x7f, 0xf3, 0x60, 0xfe, + 0x23, 0xf7, 0x0f, 0xe6, 0x4b, 0xb7, 0x45, 0x39, 0x56, 0x18, 0xe8, 0x12, 0x8c, 0x6c, 0x45, 0x1b, + 0xfb, 0x6d, 0x32, 0x5b, 0x60, 0xb8, 0x93, 0x02, 0x77, 0x64, 0xb5, 0x4e, 0x4b, 0xb1, 0x80, 0xa2, + 0x2b, 0x50, 0x6e, 0x3b, 0x61, 0xec, 0xc5, 0x5e, 0xe0, 0xcf, 0x16, 0x2f, 0x5a, 0x97, 0x87, 0x97, + 0x66, 0x04, 0x6a, 0xb9, 0x26, 0x01, 0x38, 0xc1, 0xa1, 0xdd, 0x08, 0x89, 0xe3, 0xde, 0xf4, 0x9b, + 0xfb, 0xb3, 0x43, 0x17, 0xad, 0xcb, 0xa5, 0xa4, 0x1b, 0x58, 0x94, 0x63, 0x85, 0x61, 0xff, 0x48, + 0x01, 0x4a, 0x8b, 0x5b, 0x5b, 0x9e, 0xef, 0xc5, 0xfb, 0xe8, 0x36, 0x8c, 0xfb, 0x81, 0x4b, 0xe4, + 0x7f, 0xf6, 0x15, 0x63, 0xcf, 0x5f, 0x5c, 0xe8, 0x5e, 0x4a, 0x0b, 0xeb, 0x1a, 0xde, 0xd2, 0xf4, + 0xfd, 0x83, 0xf9, 0x71, 0xbd, 0x04, 0x1b, 0x74, 0x10, 0x86, 0xb1, 0x76, 0xe0, 0x2a, 0xb2, 0x05, + 0x46, 0x76, 0x3e, 0x8b, 0x6c, 0x2d, 0x41, 0x5b, 0x9a, 0xba, 0x7f, 0x30, 0x3f, 0xa6, 0x15, 0x60, + 0x9d, 0x08, 0xda, 0x84, 0x29, 0xfa, 0xd7, 0x8f, 0x3d, 0x45, 0xb7, 0xc8, 0xe8, 0x3e, 0x91, 0x47, + 0x57, 0x43, 0x5d, 0x3a, 0x75, 0xff, 0x60, 0x7e, 0x2a, 0x55, 0x88, 0xd3, 0x04, 0xed, 0xf7, 0x60, + 0x72, 0x31, 0x8e, 0x9d, 0xc6, 0x0e, 0x71, 0xf9, 0x0c, 0xa2, 0x17, 0x61, 0xc8, 0x77, 0x5a, 0x44, + 0xcc, 0xef, 0x45, 0x31, 0xb0, 0x43, 0xeb, 0x4e, 0x8b, 0x1c, 0x1e, 0xcc, 0x4f, 0xdf, 0xf2, 0xbd, + 0x77, 0x3b, 0x62, 0x55, 0xd0, 0x32, 0xcc, 0xb0, 0xd1, 0xf3, 0x00, 0x2e, 0xd9, 0xf3, 0x1a, 0xa4, + 0xe6, 0xc4, 0x3b, 0x62, 0xbe, 0x91, 0xa8, 0x0b, 0x15, 0x05, 0xc1, 0x1a, 0x96, 0x7d, 0x0f, 0xca, + 0x8b, 0x7b, 0x81, 0xe7, 0xd6, 0x02, 0x37, 0x42, 0xbb, 0x30, 0xd5, 0x0e, 0xc9, 0x16, 0x09, 0x55, + 0xd1, 0xac, 0x75, 0xb1, 0x78, 0x79, 0xec, 0xf9, 0xcb, 0x99, 0x1f, 0x6b, 0xa2, 0xae, 0xf8, 0x71, + 0xb8, 0xbf, 0xf4, 0x88, 0x68, 0x6f, 0x2a, 0x05, 0xc5, 0x69, 0xca, 0xf6, 0xbf, 0x2c, 0xc0, 0x99, + 0xc5, 0xf7, 0x3a, 0x21, 0xa9, 0x78, 0xd1, 0x6e, 0x7a, 0x85, 0xbb, 0x5e, 0xb4, 0xbb, 0x9e, 0x8c, + 0x80, 0x5a, 0x5a, 0x15, 0x51, 0x8e, 0x15, 0x06, 0x7a, 0x16, 0x46, 0xe9, 0xef, 0x5b, 0xb8, 0x2a, + 0x3e, 0xf9, 0x94, 0x40, 0x1e, 0xab, 0x38, 0xb1, 0x53, 0xe1, 0x20, 0x2c, 0x71, 0xd0, 0x1a, 0x8c, + 0x35, 0xd8, 0x86, 0xdc, 0x5e, 0x0b, 0x5c, 0xc2, 0x26, 0xb3, 0xbc, 0xf4, 0x34, 0x45, 0x5f, 0x4e, + 0x8a, 0x0f, 0x0f, 0xe6, 0x67, 0x79, 0xdf, 0x04, 0x09, 0x0d, 0x86, 0xf5, 0xfa, 0xc8, 0x56, 0xfb, + 0x6b, 0x88, 0x51, 0x82, 0x8c, 0xbd, 0x75, 0x59, 0xdb, 0x2a, 0xc3, 0x6c, 0xab, 0x8c, 0x67, 0x6f, + 0x13, 0xf4, 0x1c, 0x0c, 0xed, 0x7a, 0xbe, 0x3b, 0x3b, 0xc2, 0x68, 0x9d, 0xa7, 0x73, 0x7e, 0xdd, + 0xf3, 0xdd, 0xc3, 0x83, 0xf9, 0x19, 0xa3, 0x3b, 0xb4, 0x10, 0x33, 0x54, 0xfb, 0xcf, 0x2c, 0x98, + 0x67, 0xb0, 0x55, 0xaf, 0x49, 0x6a, 0x24, 0x8c, 0xbc, 0x28, 0x26, 0x7e, 0x6c, 0x0c, 0xe8, 0xf3, + 0x00, 0x11, 0x69, 0x84, 0x24, 0xd6, 0x86, 0x54, 0x2d, 0x8c, 0xba, 0x82, 0x60, 0x0d, 0x8b, 0x1e, + 0x08, 0xd1, 0x8e, 0x13, 0xb2, 0xf5, 0x25, 0x06, 0x56, 0x1d, 0x08, 0x75, 0x09, 0xc0, 0x09, 0x8e, + 0x71, 0x20, 0x14, 0xfb, 0x1d, 0x08, 0xe8, 0xd3, 0x30, 0x95, 0x34, 0x16, 0xb5, 0x9d, 0x86, 0x1c, + 0x40, 0xb6, 0x65, 0xea, 0x26, 0x08, 0xa7, 0x71, 0xed, 0xbf, 0x67, 0x89, 0xc5, 0x43, 0xbf, 0xfa, + 0x03, 0xfe, 0xad, 0xf6, 0x2f, 0x5b, 0x30, 0xba, 0xe4, 0xf9, 0xae, 0xe7, 0x6f, 0xa3, 0x2f, 0x40, + 0x89, 0xde, 0x4d, 0xae, 0x13, 0x3b, 0xe2, 0xdc, 0xfb, 0x84, 0xb6, 0xb7, 0xd4, 0x55, 0xb1, 0xd0, + 0xde, 0xdd, 0xa6, 0x05, 0xd1, 0x02, 0xc5, 0xa6, 0xbb, 0xed, 0xe6, 0xe6, 0x3b, 0xa4, 0x11, 0xaf, + 0x91, 0xd8, 0x49, 0x3e, 0x27, 0x29, 0xc3, 0x8a, 0x2a, 0xba, 0x0e, 0x23, 0xb1, 0x13, 0x6e, 0x93, + 0x58, 0x1c, 0x80, 0x99, 0x07, 0x15, 0xaf, 0x89, 0xe9, 0x8e, 0x24, 0x7e, 0x83, 0x24, 0xd7, 0xc2, + 0x06, 0xab, 0x8a, 0x05, 0x09, 0xfb, 0x87, 0x46, 0xe1, 0xdc, 0x72, 0xbd, 0x9a, 0xb3, 0xae, 0x2e, + 0xc1, 0x88, 0x1b, 0x7a, 0x7b, 0x24, 0x14, 0xe3, 0xac, 0xa8, 0x54, 0x58, 0x29, 0x16, 0x50, 0xf4, + 0x0a, 0x8c, 0xf3, 0x0b, 0xe9, 0x9a, 0xe3, 0xbb, 0x4d, 0x39, 0xc4, 0xa7, 0x05, 0xf6, 0xf8, 0x6d, + 0x0d, 0x86, 0x0d, 0xcc, 0x23, 0x2e, 0xaa, 0x4b, 0xa9, 0xcd, 0x98, 0x77, 0xd9, 0x7d, 0xc9, 0x82, + 0x69, 0xde, 0xcc, 0x62, 0x1c, 0x87, 0xde, 0x66, 0x27, 0x26, 0xd1, 0xec, 0x30, 0x3b, 0xe9, 0x96, + 0xb3, 0x46, 0x2b, 0x77, 0x04, 0x16, 0x6e, 0xa7, 0xa8, 0xf0, 0x43, 0x70, 0x56, 0xb4, 0x3b, 0x9d, + 0x06, 0xe3, 0xae, 0x66, 0xd1, 0x77, 0x59, 0x30, 0xd7, 0x08, 0xfc, 0x38, 0x0c, 0x9a, 0x4d, 0x12, + 0xd6, 0x3a, 0x9b, 0x4d, 0x2f, 0xda, 0xe1, 0xeb, 0x14, 0x93, 0x2d, 0x76, 0x12, 0xe4, 0xcc, 0xa1, + 0x42, 0x12, 0x73, 0x78, 0xe1, 0xfe, 0xc1, 0xfc, 0xdc, 0x72, 0x2e, 0x29, 0xdc, 0xa3, 0x19, 0xb4, + 0x0b, 0x88, 0x5e, 0xa5, 0xf5, 0xd8, 0xd9, 0x26, 0x49, 0xe3, 0xa3, 0x83, 0x37, 0x7e, 0xf6, 0xfe, + 0xc1, 0x3c, 0x5a, 0xef, 0x22, 0x81, 0x33, 0xc8, 0xa2, 0x77, 0xe1, 0x34, 0x2d, 0xed, 0xfa, 0xd6, + 0xd2, 0xe0, 0xcd, 0xcd, 0xde, 0x3f, 0x98, 0x3f, 0xbd, 0x9e, 0x41, 0x04, 0x67, 0x92, 0x46, 0xdf, + 0x69, 0xc1, 0xb9, 0xe4, 0xf3, 0x57, 0xee, 0xb5, 0x1d, 0xdf, 0x4d, 0x1a, 0x2e, 0x0f, 0xde, 0x30, + 0x3d, 0x93, 0xcf, 0x2d, 0xe7, 0x51, 0xc2, 0xf9, 0x8d, 0xcc, 0x2d, 0xc3, 0x99, 0xcc, 0xd5, 0x82, + 0xa6, 0xa1, 0xb8, 0x4b, 0x38, 0x17, 0x54, 0xc6, 0xf4, 0x27, 0x3a, 0x0d, 0xc3, 0x7b, 0x4e, 0xb3, + 0x23, 0x36, 0x0a, 0xe6, 0x7f, 0x3e, 0x55, 0x78, 0xc5, 0xb2, 0xff, 0x55, 0x11, 0xa6, 0x96, 0xeb, + 0xd5, 0x07, 0xda, 0x85, 0xfa, 0x35, 0x54, 0xe8, 0x79, 0x0d, 0x25, 0x97, 0x5a, 0x31, 0xf7, 0x52, + 0xfb, 0xbf, 0x33, 0xb6, 0xd0, 0x10, 0xdb, 0x42, 0xdf, 0x94, 0xb3, 0x85, 0x8e, 0x79, 0xe3, 0xec, + 0xe5, 0xac, 0xa2, 0x61, 0x36, 0x99, 0x99, 0x1c, 0xcb, 0x8d, 0xa0, 0xe1, 0x34, 0xd3, 0x47, 0xdf, + 0x11, 0x97, 0xd2, 0xf1, 0xcc, 0x63, 0x03, 0xc6, 0x97, 0x9d, 0xb6, 0xb3, 0xe9, 0x35, 0xbd, 0xd8, + 0x23, 0x11, 0x7a, 0x12, 0x8a, 0x8e, 0xeb, 0x32, 0x6e, 0xab, 0xbc, 0x74, 0xe6, 0xfe, 0xc1, 0x7c, + 0x71, 0xd1, 0xa5, 0xd7, 0x3e, 0x28, 0xac, 0x7d, 0x4c, 0x31, 0xd0, 0xc7, 0x61, 0xc8, 0x0d, 0x83, + 0xf6, 0x6c, 0x81, 0x61, 0xd2, 0x5d, 0x37, 0x54, 0x09, 0x83, 0x76, 0x0a, 0x95, 0xe1, 0xd8, 0xbf, + 0x56, 0x80, 0xc7, 0x96, 0x49, 0x7b, 0x67, 0xb5, 0x9e, 0x73, 0x7e, 0x5f, 0x86, 0x52, 0x2b, 0xf0, + 0xbd, 0x38, 0x08, 0x23, 0xd1, 0x34, 0x5b, 0x11, 0x6b, 0xa2, 0x0c, 0x2b, 0x28, 0xba, 0x08, 0x43, + 0xed, 0x84, 0xa9, 0x1c, 0x97, 0x0c, 0x29, 0x63, 0x27, 0x19, 0x84, 0x62, 0x74, 0x22, 0x12, 0x8a, + 0x15, 0xa3, 0x30, 0x6e, 0x45, 0x24, 0xc4, 0x0c, 0x92, 0xdc, 0xcc, 0xf4, 0xce, 0x16, 0x27, 0x74, + 0xea, 0x66, 0xa6, 0x10, 0xac, 0x61, 0xa1, 0x1a, 0x94, 0xa3, 0xd4, 0xcc, 0x0e, 0xb4, 0x4d, 0x27, + 0xd8, 0xd5, 0xad, 0x66, 0x32, 0x21, 0x62, 0xdc, 0x28, 0x23, 0x7d, 0xaf, 0xee, 0xaf, 0x16, 0x00, + 0xf1, 0x21, 0xfc, 0x2b, 0x36, 0x70, 0xb7, 0xba, 0x07, 0x6e, 0xf0, 0x2d, 0x71, 0x5c, 0xa3, 0xf7, + 0xe7, 0x16, 0x3c, 0xb6, 0xec, 0xf9, 0x2e, 0x09, 0x73, 0x16, 0xe0, 0xc3, 0x79, 0xcb, 0x1e, 0x8d, + 0x69, 0x30, 0x96, 0xd8, 0xd0, 0x31, 0x2c, 0x31, 0xfb, 0x4f, 0x2c, 0x40, 0xfc, 0xb3, 0x3f, 0x70, + 0x1f, 0x7b, 0xab, 0xfb, 0x63, 0x8f, 0x61, 0x59, 0xd8, 0x37, 0x60, 0x72, 0xb9, 0xe9, 0x11, 0x3f, + 0xae, 0xd6, 0x96, 0x03, 0x7f, 0xcb, 0xdb, 0x46, 0x9f, 0x82, 0xc9, 0xd8, 0x6b, 0x91, 0xa0, 0x13, + 0xd7, 0x49, 0x23, 0xf0, 0xd9, 0x4b, 0xd2, 0xba, 0x3c, 0xbc, 0x84, 0xee, 0x1f, 0xcc, 0x4f, 0x6e, + 0x18, 0x10, 0x9c, 0xc2, 0xb4, 0x7f, 0x97, 0x8e, 0x5f, 0xd0, 0x6a, 0x07, 0x3e, 0xf1, 0xe3, 0xe5, + 0xc0, 0x77, 0xb9, 0xc4, 0xe1, 0x53, 0x30, 0x14, 0xd3, 0xf1, 0xe0, 0x63, 0x77, 0x49, 0x6e, 0x14, + 0x3a, 0x0a, 0x87, 0x07, 0xf3, 0x67, 0xbb, 0x6b, 0xb0, 0x71, 0x62, 0x75, 0xd0, 0x37, 0xc1, 0x48, + 0x14, 0x3b, 0x71, 0x27, 0x12, 0xa3, 0xf9, 0xb8, 0x1c, 0xcd, 0x3a, 0x2b, 0x3d, 0x3c, 0x98, 0x9f, + 0x52, 0xd5, 0x78, 0x11, 0x16, 0x15, 0xd0, 0x53, 0x30, 0xda, 0x22, 0x51, 0xe4, 0x6c, 0xcb, 0xdb, + 0x70, 0x4a, 0xd4, 0x1d, 0x5d, 0xe3, 0xc5, 0x58, 0xc2, 0xd1, 0x13, 0x30, 0x4c, 0xc2, 0x30, 0x08, + 0xc5, 0x1e, 0x9d, 0x10, 0x88, 0xc3, 0x2b, 0xb4, 0x10, 0x73, 0x98, 0xfd, 0xef, 0x2c, 0x98, 0x52, + 0x7d, 0xe5, 0x6d, 0x9d, 0xc0, 0xab, 0xe0, 0x2d, 0x80, 0x86, 0xfc, 0xc0, 0x88, 0xdd, 0x1e, 0x63, + 0xcf, 0x5f, 0xca, 0xbc, 0xa8, 0xbb, 0x86, 0x31, 0xa1, 0xac, 0x8a, 0x22, 0xac, 0x51, 0xb3, 0xff, + 0xa9, 0x05, 0xa7, 0x52, 0x5f, 0x74, 0xc3, 0x8b, 0x62, 0xf4, 0x76, 0xd7, 0x57, 0x2d, 0x0c, 0xf6, + 0x55, 0xb4, 0x36, 0xfb, 0x26, 0xb5, 0x94, 0x65, 0x89, 0xf6, 0x45, 0xd7, 0x60, 0xd8, 0x8b, 0x49, + 0x4b, 0x7e, 0xcc, 0x13, 0x3d, 0x3f, 0x86, 0xf7, 0x2a, 0x99, 0x91, 0x2a, 0xad, 0x89, 0x39, 0x01, + 0xfb, 0xaf, 0x15, 0xa1, 0xcc, 0x97, 0xed, 0x9a, 0xd3, 0x3e, 0x81, 0xb9, 0xa8, 0xc2, 0x10, 0xa3, + 0xce, 0x3b, 0xfe, 0x64, 0x76, 0xc7, 0x45, 0x77, 0x16, 0xe8, 0x93, 0x9f, 0x33, 0x47, 0xea, 0x6a, + 0xa0, 0x45, 0x98, 0x91, 0x40, 0x0e, 0xc0, 0xa6, 0xe7, 0x3b, 0xe1, 0x3e, 0x2d, 0x9b, 0x2d, 0x32, + 0x82, 0xcf, 0xf6, 0x26, 0xb8, 0xa4, 0xf0, 0x39, 0x59, 0xd5, 0xd7, 0x04, 0x80, 0x35, 0xa2, 0x73, + 0x2f, 0x43, 0x59, 0x21, 0x1f, 0x85, 0xc7, 0x99, 0xfb, 0x34, 0x4c, 0xa5, 0xda, 0xea, 0x57, 0x7d, + 0x5c, 0x67, 0x91, 0x7e, 0x85, 0x9d, 0x02, 0xa2, 0xd7, 0x2b, 0xfe, 0x9e, 0x38, 0x45, 0xdf, 0x83, + 0xd3, 0xcd, 0x8c, 0xc3, 0x49, 0x4c, 0xd5, 0xe0, 0x87, 0xd9, 0x63, 0xe2, 0xb3, 0x4f, 0x67, 0x41, + 0x71, 0x66, 0x1b, 0xf4, 0xda, 0x0f, 0xda, 0x74, 0xcd, 0x3b, 0x4d, 0x9d, 0x83, 0xbe, 0x29, 0xca, + 0xb0, 0x82, 0xd2, 0x23, 0xec, 0xb4, 0xea, 0xfc, 0x75, 0xb2, 0x5f, 0x27, 0x4d, 0xd2, 0x88, 0x83, + 0xf0, 0xeb, 0xda, 0xfd, 0xf3, 0x7c, 0xf4, 0xf9, 0x09, 0x38, 0x26, 0x08, 0x14, 0xaf, 0x93, 0x7d, + 0x3e, 0x15, 0xfa, 0xd7, 0x15, 0x7b, 0x7e, 0xdd, 0xcf, 0x5b, 0x30, 0xa1, 0xbe, 0xee, 0x04, 0xb6, + 0xfa, 0x92, 0xb9, 0xd5, 0xcf, 0xf7, 0x5c, 0xe0, 0x39, 0x9b, 0xfc, 0xab, 0x05, 0x38, 0xa7, 0x70, + 0x28, 0xbb, 0xcf, 0xff, 0x88, 0x55, 0x75, 0x05, 0xca, 0xbe, 0x12, 0x44, 0x59, 0xa6, 0x04, 0x28, + 0x11, 0x43, 0x25, 0x38, 0x94, 0x6b, 0xf3, 0x13, 0x69, 0xd1, 0xb8, 0x2e, 0xa1, 0x15, 0xd2, 0xd8, + 0x25, 0x28, 0x76, 0x3c, 0x57, 0xdc, 0x19, 0x9f, 0x90, 0xa3, 0x7d, 0xab, 0x5a, 0x39, 0x3c, 0x98, + 0x7f, 0x3c, 0x4f, 0x3b, 0x40, 0x2f, 0xab, 0x68, 0xe1, 0x56, 0xb5, 0x82, 0x69, 0x65, 0xb4, 0x08, + 0x53, 0x52, 0x01, 0x72, 0x9b, 0x72, 0x50, 0x81, 0x2f, 0xae, 0x16, 0x25, 0x66, 0xc5, 0x26, 0x18, + 0xa7, 0xf1, 0x51, 0x05, 0xa6, 0x77, 0x3b, 0x9b, 0xa4, 0x49, 0x62, 0xfe, 0xc1, 0xd7, 0x09, 0x17, + 0x42, 0x96, 0x93, 0xc7, 0xd6, 0xf5, 0x14, 0x1c, 0x77, 0xd5, 0xb0, 0xff, 0x92, 0x1d, 0xf1, 0x62, + 0xf4, 0x6a, 0x61, 0x40, 0x17, 0x16, 0xa5, 0xfe, 0xf5, 0x5c, 0xce, 0x83, 0xac, 0x8a, 0xeb, 0x64, + 0x7f, 0x23, 0xa0, 0xcc, 0x76, 0xf6, 0xaa, 0x30, 0xd6, 0xfc, 0x50, 0xcf, 0x35, 0xff, 0x0b, 0x05, + 0x38, 0xa3, 0x46, 0xc0, 0xe0, 0xeb, 0xfe, 0xaa, 0x8f, 0xc1, 0x73, 0x30, 0xe6, 0x92, 0x2d, 0xa7, + 0xd3, 0x8c, 0x95, 0x44, 0x7c, 0x98, 0x6b, 0x45, 0x2a, 0x49, 0x31, 0xd6, 0x71, 0x8e, 0x30, 0x6c, + 0x3f, 0x39, 0xc6, 0xee, 0xd6, 0xd8, 0xa1, 0x6b, 0x5c, 0xed, 0x1a, 0x2b, 0x77, 0xd7, 0x3c, 0x01, + 0xc3, 0x5e, 0x8b, 0xf2, 0x5a, 0x05, 0x93, 0x85, 0xaa, 0xd2, 0x42, 0xcc, 0x61, 0xe8, 0x63, 0x30, + 0xda, 0x08, 0x5a, 0x2d, 0xc7, 0x77, 0xd9, 0x95, 0x57, 0x5e, 0x1a, 0xa3, 0xec, 0xd8, 0x32, 0x2f, + 0xc2, 0x12, 0x86, 0x1e, 0x83, 0x21, 0x27, 0xdc, 0xe6, 0x62, 0x89, 0xf2, 0x52, 0x89, 0xb6, 0xb4, + 0x18, 0x6e, 0x47, 0x98, 0x95, 0xd2, 0x57, 0xd5, 0xdd, 0x20, 0xdc, 0xf5, 0xfc, 0xed, 0x8a, 0x17, + 0x8a, 0x2d, 0xa1, 0xee, 0xc2, 0x3b, 0x0a, 0x82, 0x35, 0x2c, 0xb4, 0x0a, 0xc3, 0xed, 0x20, 0x8c, + 0xa3, 0xd9, 0x11, 0x36, 0xdc, 0x8f, 0xe7, 0x1c, 0x44, 0xfc, 0x6b, 0x6b, 0x41, 0x18, 0x27, 0x1f, + 0x40, 0xff, 0x45, 0x98, 0x57, 0x47, 0x37, 0x60, 0x94, 0xf8, 0x7b, 0xab, 0x61, 0xd0, 0x9a, 0x3d, + 0x95, 0x4f, 0x69, 0x85, 0xa3, 0xf0, 0x65, 0x96, 0xb0, 0x9d, 0xa2, 0x18, 0x4b, 0x12, 0xe8, 0x9b, + 0xa0, 0x48, 0xfc, 0xbd, 0xd9, 0x51, 0x46, 0x69, 0x2e, 0x87, 0xd2, 0x6d, 0x27, 0x4c, 0xce, 0xfc, + 0x15, 0x7f, 0x0f, 0xd3, 0x3a, 0xe8, 0xb3, 0x50, 0x96, 0x07, 0x46, 0x24, 0xe4, 0x6f, 0x99, 0x0b, + 0x56, 0x1e, 0x33, 0x98, 0xbc, 0xdb, 0xf1, 0x42, 0xd2, 0x22, 0x7e, 0x1c, 0x25, 0x27, 0xa4, 0x84, + 0x46, 0x38, 0xa1, 0x86, 0x3e, 0x2b, 0x85, 0xbe, 0x6b, 0x41, 0xc7, 0x8f, 0xa3, 0xd9, 0x32, 0xeb, + 0x5e, 0xa6, 0x3a, 0xee, 0x76, 0x82, 0x97, 0x96, 0x0a, 0xf3, 0xca, 0xd8, 0x20, 0x85, 0x3e, 0x07, + 0x13, 0xfc, 0x3f, 0x57, 0x6a, 0x45, 0xb3, 0x67, 0x18, 0xed, 0x8b, 0xf9, 0xb4, 0x39, 0xe2, 0xd2, + 0x19, 0x41, 0x7c, 0x42, 0x2f, 0x8d, 0xb0, 0x49, 0x0d, 0x61, 0x98, 0x68, 0x7a, 0x7b, 0xc4, 0x27, + 0x51, 0x54, 0x0b, 0x83, 0x4d, 0x32, 0x0b, 0x6c, 0x60, 0xce, 0x65, 0x2b, 0xc1, 0x82, 0x4d, 0xb2, + 0x34, 0x43, 0x69, 0xde, 0xd0, 0xeb, 0x60, 0x93, 0x04, 0xba, 0x05, 0x93, 0xf4, 0x11, 0xe6, 0x25, + 0x44, 0xc7, 0xfa, 0x11, 0x65, 0x4f, 0x25, 0x6c, 0x54, 0xc2, 0x29, 0x22, 0xe8, 0x0d, 0x28, 0x37, + 0xbd, 0x2d, 0xd2, 0xd8, 0x6f, 0x34, 0xc9, 0xec, 0x38, 0xa3, 0x98, 0x79, 0x06, 0xdc, 0x90, 0x48, + 0xfc, 0x11, 0xa7, 0xfe, 0xe2, 0xa4, 0x3a, 0xba, 0x0d, 0x67, 0x63, 0x12, 0xb6, 0x3c, 0xdf, 0xa1, + 0x7b, 0x57, 0x3c, 0x6e, 0x98, 0x2a, 0x71, 0x82, 0x6d, 0x8e, 0x0b, 0x62, 0xf0, 0xce, 0x6e, 0x64, + 0x62, 0xe1, 0x9c, 0xda, 0xe8, 0x1e, 0xcc, 0x66, 0x40, 0x82, 0xa6, 0xd7, 0xd8, 0x9f, 0x3d, 0xcd, + 0x28, 0xbf, 0x26, 0x28, 0xcf, 0x6e, 0xe4, 0xe0, 0x1d, 0xf6, 0x80, 0xe1, 0x5c, 0xea, 0xe8, 0x26, + 0x4c, 0xb1, 0x03, 0xa3, 0xd6, 0x69, 0x36, 0x45, 0x83, 0x93, 0xac, 0xc1, 0x8f, 0xc9, 0xeb, 0xb3, + 0x6a, 0x82, 0x0f, 0x0f, 0xe6, 0x21, 0xf9, 0x87, 0xd3, 0xb5, 0xd1, 0x26, 0xd3, 0x5a, 0x75, 0x42, + 0x2f, 0xde, 0xa7, 0xdb, 0x9c, 0xdc, 0x8b, 0x67, 0xa7, 0x7a, 0x4a, 0x0c, 0x74, 0x54, 0xa5, 0xda, + 0xd2, 0x0b, 0x71, 0x9a, 0x20, 0x3d, 0x01, 0xa3, 0xd8, 0xf5, 0xfc, 0xd9, 0x69, 0x76, 0xb0, 0xaa, + 0x03, 0xa4, 0x4e, 0x0b, 0x31, 0x87, 0x31, 0x8d, 0x15, 0xfd, 0x71, 0x93, 0x5e, 0x34, 0x33, 0x0c, + 0x31, 0xd1, 0x58, 0x49, 0x00, 0x4e, 0x70, 0x28, 0xef, 0x17, 0xc7, 0xfb, 0xb3, 0x88, 0xa1, 0xaa, + 0x73, 0x60, 0x63, 0xe3, 0xb3, 0x98, 0x96, 0xdb, 0x9b, 0x30, 0xa9, 0xce, 0x2d, 0x36, 0x26, 0x68, + 0x1e, 0x86, 0x19, 0xb7, 0x23, 0xe4, 0x5b, 0x65, 0xda, 0x05, 0xc6, 0x09, 0x61, 0x5e, 0xce, 0xba, + 0xe0, 0xbd, 0x47, 0x96, 0xf6, 0x63, 0xc2, 0x5f, 0xd5, 0x45, 0xad, 0x0b, 0x12, 0x80, 0x13, 0x1c, + 0xfb, 0x7f, 0x73, 0xae, 0x31, 0x39, 0x1c, 0x07, 0xb8, 0x0e, 0x9e, 0x81, 0xd2, 0x4e, 0x10, 0xc5, + 0x14, 0x9b, 0xb5, 0x31, 0x9c, 0xf0, 0x89, 0xd7, 0x44, 0x39, 0x56, 0x18, 0xe8, 0x55, 0x98, 0x68, + 0xe8, 0x0d, 0x88, 0xbb, 0x4c, 0xed, 0x7a, 0xa3, 0x75, 0x6c, 0xe2, 0xa2, 0x57, 0xa0, 0xc4, 0xac, + 0x30, 0x1a, 0x41, 0x53, 0x30, 0x59, 0xf2, 0x42, 0x2e, 0xd5, 0x44, 0xf9, 0xa1, 0xf6, 0x1b, 0x2b, + 0x6c, 0x74, 0x09, 0x46, 0x68, 0x17, 0xaa, 0x35, 0x71, 0x8b, 0x28, 0x51, 0xcd, 0x35, 0x56, 0x8a, + 0x05, 0xd4, 0xfe, 0xff, 0x0b, 0xda, 0x28, 0xd3, 0x17, 0x29, 0x41, 0x35, 0x18, 0xbd, 0xeb, 0x78, + 0xb1, 0xe7, 0x6f, 0x0b, 0x76, 0xe1, 0xa9, 0x9e, 0x57, 0x0a, 0xab, 0x74, 0x87, 0x57, 0xe0, 0x97, + 0x9e, 0xf8, 0x83, 0x25, 0x19, 0x4a, 0x31, 0xec, 0xf8, 0x3e, 0xa5, 0x58, 0x18, 0x94, 0x22, 0xe6, + 0x15, 0x38, 0x45, 0xf1, 0x07, 0x4b, 0x32, 0xe8, 0x6d, 0x00, 0xb9, 0xc3, 0x88, 0x2b, 0xac, 0x1f, + 0x9e, 0xe9, 0x4f, 0x74, 0x43, 0xd5, 0x59, 0x9a, 0xa4, 0x57, 0x6a, 0xf2, 0x1f, 0x6b, 0xf4, 0xec, + 0x98, 0xb1, 0x55, 0xdd, 0x9d, 0x41, 0xdf, 0x4a, 0x97, 0xb8, 0x13, 0xc6, 0xc4, 0x5d, 0x8c, 0xc5, + 0xe0, 0x7c, 0x7c, 0xb0, 0x37, 0xc5, 0x86, 0xd7, 0x22, 0xfa, 0x76, 0x10, 0x44, 0x70, 0x42, 0xcf, + 0xfe, 0xa5, 0x22, 0xcc, 0xe6, 0x75, 0x97, 0x2e, 0x3a, 0x72, 0xcf, 0x8b, 0x97, 0x29, 0x37, 0x64, + 0x99, 0x8b, 0x6e, 0x45, 0x94, 0x63, 0x85, 0x41, 0x67, 0x3f, 0xf2, 0xb6, 0xe5, 0x93, 0x70, 0x38, + 0x99, 0xfd, 0x3a, 0x2b, 0xc5, 0x02, 0x4a, 0xf1, 0x42, 0xe2, 0x44, 0xc2, 0xbc, 0x46, 0x5b, 0x25, + 0x98, 0x95, 0x62, 0x01, 0xd5, 0xe5, 0x4d, 0x43, 0x7d, 0xe4, 0x4d, 0xc6, 0x10, 0x0d, 0x1f, 0xef, + 0x10, 0xa1, 0xcf, 0x03, 0x6c, 0x79, 0xbe, 0x17, 0xed, 0x30, 0xea, 0x23, 0x47, 0xa6, 0xae, 0x78, + 0xa9, 0x55, 0x45, 0x05, 0x6b, 0x14, 0xd1, 0x4b, 0x30, 0xa6, 0x36, 0x60, 0xb5, 0xc2, 0x74, 0x8d, + 0x9a, 0xed, 0x46, 0x72, 0x1a, 0x55, 0xb0, 0x8e, 0x67, 0xbf, 0x93, 0x5e, 0x2f, 0x62, 0x07, 0x68, + 0xe3, 0x6b, 0x0d, 0x3a, 0xbe, 0x85, 0xde, 0xe3, 0x6b, 0xff, 0x7a, 0x11, 0xa6, 0x8c, 0xc6, 0x3a, + 0xd1, 0x00, 0x67, 0xd6, 0x55, 0x7a, 0x80, 0x3b, 0x31, 0x11, 0xfb, 0xcf, 0xee, 0xbf, 0x55, 0xf4, + 0x43, 0x9e, 0xee, 0x00, 0x5e, 0x1f, 0x7d, 0x1e, 0xca, 0x4d, 0x27, 0x62, 0xb2, 0x2b, 0x22, 0xf6, + 0xdd, 0x20, 0xc4, 0x92, 0x77, 0x84, 0x13, 0xc5, 0xda, 0xad, 0xc9, 0x69, 0x27, 0x24, 0xe9, 0x4d, + 0x43, 0xd9, 0x09, 0x69, 0xbf, 0xa5, 0x3a, 0x41, 0x79, 0x8e, 0x7d, 0xcc, 0x61, 0xe8, 0x15, 0x18, + 0x0f, 0x09, 0x5b, 0x15, 0xcb, 0x94, 0xf9, 0x62, 0xcb, 0x6c, 0x38, 0xe1, 0xd2, 0xb0, 0x06, 0xc3, + 0x06, 0x66, 0xc2, 0xca, 0x8f, 0xf4, 0x60, 0xe5, 0x9f, 0x82, 0x51, 0xf6, 0x43, 0xad, 0x00, 0x35, + 0x1b, 0x55, 0x5e, 0x8c, 0x25, 0x3c, 0xbd, 0x60, 0x4a, 0x03, 0x2e, 0x98, 0x8f, 0xc3, 0x64, 0xc5, + 0x21, 0xad, 0xc0, 0x5f, 0xf1, 0xdd, 0x76, 0xe0, 0xf9, 0x31, 0x9a, 0x85, 0x21, 0x76, 0x3b, 0xf0, + 0xbd, 0x3d, 0x44, 0x29, 0xe0, 0x21, 0xca, 0x98, 0xdb, 0xdb, 0x70, 0xa6, 0x12, 0xdc, 0xf5, 0xef, + 0x3a, 0xa1, 0xbb, 0x58, 0xab, 0x6a, 0xef, 0xdc, 0x75, 0xf9, 0xce, 0xe2, 0xf6, 0x50, 0x99, 0x67, + 0xaa, 0x56, 0x93, 0xb3, 0x97, 0xab, 0x5e, 0x93, 0xe4, 0x48, 0x23, 0xfe, 0x46, 0xc1, 0x68, 0x29, + 0xc1, 0x57, 0x0a, 0x23, 0x2b, 0x57, 0x61, 0xf4, 0x26, 0x94, 0xb6, 0x3c, 0xd2, 0x74, 0x31, 0xd9, + 0x12, 0x4b, 0xec, 0xc9, 0x7c, 0x13, 0x8f, 0x55, 0x8a, 0x29, 0xa5, 0x4f, 0xfc, 0x95, 0xb6, 0x2a, + 0x2a, 0x63, 0x45, 0x06, 0xed, 0xc2, 0xb4, 0x64, 0xdc, 0x25, 0x54, 0x2c, 0xb8, 0xa7, 0x7a, 0xbd, + 0x06, 0x4c, 0xe2, 0xa7, 0xef, 0x1f, 0xcc, 0x4f, 0xe3, 0x14, 0x19, 0xdc, 0x45, 0x98, 0x3e, 0xcb, + 0x5a, 0xf4, 0x68, 0x1d, 0x62, 0xc3, 0xcf, 0x9e, 0x65, 0xec, 0x85, 0xc9, 0x4a, 0xed, 0x1f, 0xb3, + 0xe0, 0x91, 0xae, 0x91, 0x11, 0x2f, 0xed, 0x63, 0x9e, 0x85, 0xf4, 0xcb, 0xb7, 0xd0, 0xff, 0xe5, + 0x6b, 0xff, 0x9c, 0x05, 0xa7, 0x57, 0x5a, 0xed, 0x78, 0xbf, 0xe2, 0x99, 0xda, 0x9d, 0x97, 0x61, + 0xa4, 0x45, 0x5c, 0xaf, 0xd3, 0x12, 0x33, 0x37, 0x2f, 0x8f, 0x9f, 0x35, 0x56, 0x7a, 0x78, 0x30, + 0x3f, 0x51, 0x8f, 0x83, 0xd0, 0xd9, 0x26, 0xbc, 0x00, 0x0b, 0x74, 0x76, 0x88, 0x7b, 0xef, 0x91, + 0x1b, 0x5e, 0xcb, 0x93, 0x26, 0x3b, 0x3d, 0x65, 0x67, 0x0b, 0x72, 0x40, 0x17, 0xde, 0xec, 0x38, + 0x7e, 0xec, 0xc5, 0xfb, 0x42, 0x31, 0x23, 0x89, 0xe0, 0x84, 0x9e, 0xfd, 0x35, 0x0b, 0xa6, 0xe4, + 0xba, 0x5f, 0x74, 0xdd, 0x90, 0x44, 0x11, 0x9a, 0x83, 0x82, 0xd7, 0x16, 0xbd, 0x04, 0xd1, 0xcb, + 0x42, 0xb5, 0x86, 0x0b, 0x5e, 0x5b, 0xf2, 0x5b, 0xec, 0x84, 0x2b, 0x9a, 0x3a, 0xaa, 0x6b, 0xa2, + 0x1c, 0x2b, 0x0c, 0x74, 0x19, 0x4a, 0x7e, 0xe0, 0x72, 0xb3, 0x29, 0x7e, 0x57, 0xb1, 0x05, 0xb6, + 0x2e, 0xca, 0xb0, 0x82, 0xa2, 0x1a, 0x94, 0xb9, 0x45, 0x51, 0xb2, 0x68, 0x07, 0xb2, 0x4b, 0x62, + 0x5f, 0xb6, 0x21, 0x6b, 0xe2, 0x84, 0x88, 0xfd, 0x83, 0x16, 0x8c, 0xcb, 0x2f, 0x1b, 0x90, 0x99, + 0xa4, 0x5b, 0x2b, 0x61, 0x24, 0x93, 0xad, 0x45, 0x99, 0x41, 0x06, 0x31, 0x78, 0xc0, 0xe2, 0x51, + 0x78, 0x40, 0xfb, 0x47, 0x0b, 0x30, 0x29, 0xbb, 0x53, 0xef, 0x6c, 0x46, 0x24, 0x46, 0x1b, 0x50, + 0x76, 0xf8, 0x90, 0x13, 0xb9, 0x62, 0x9f, 0xc8, 0x7e, 0x9c, 0x1b, 0xf3, 0x93, 0x5c, 0xcb, 0x8b, + 0xb2, 0x36, 0x4e, 0x08, 0xa1, 0x26, 0xcc, 0xf8, 0x41, 0xcc, 0x8e, 0x68, 0x05, 0xef, 0xa5, 0x02, + 0x49, 0x53, 0x3f, 0x27, 0xa8, 0xcf, 0xac, 0xa7, 0xa9, 0xe0, 0x6e, 0xc2, 0x68, 0x45, 0x0a, 0x3c, + 0x8a, 0xf9, 0x2f, 0x6c, 0x7d, 0x16, 0xb2, 0xe5, 0x1d, 0xf6, 0xaf, 0x5a, 0x50, 0x96, 0x68, 0x27, + 0xa1, 0xed, 0x5a, 0x83, 0xd1, 0x88, 0x4d, 0x82, 0x1c, 0x1a, 0xbb, 0x57, 0xc7, 0xf9, 0x7c, 0x25, + 0x37, 0x0f, 0xff, 0x1f, 0x61, 0x49, 0x83, 0xc9, 0xbb, 0x55, 0xf7, 0x3f, 0x20, 0xf2, 0x6e, 0xd5, + 0x9f, 0x9c, 0x1b, 0xe6, 0x0f, 0x59, 0x9f, 0x35, 0x01, 0x12, 0x65, 0x90, 0xda, 0x21, 0xd9, 0xf2, + 0xee, 0xa5, 0x19, 0xa4, 0x1a, 0x2b, 0xc5, 0x02, 0x8a, 0xde, 0x86, 0xf1, 0x86, 0x14, 0x74, 0x26, + 0xdb, 0xf5, 0x52, 0x4f, 0xa1, 0xbb, 0xd2, 0xcf, 0x70, 0x23, 0xed, 0x65, 0xad, 0x3e, 0x36, 0xa8, + 0x99, 0xea, 0xf6, 0x62, 0x3f, 0x75, 0x7b, 0x42, 0x37, 0x5f, 0xf9, 0xfc, 0xe3, 0x16, 0x8c, 0x70, + 0x01, 0xd7, 0x60, 0xf2, 0x45, 0x4d, 0x5d, 0x95, 0x8c, 0xdd, 0x6d, 0x5a, 0x28, 0xd4, 0x4f, 0x68, + 0x0d, 0xca, 0xec, 0x07, 0x13, 0xd0, 0x15, 0xf3, 0xad, 0xd3, 0x79, 0xab, 0x7a, 0x07, 0x6f, 0xcb, + 0x6a, 0x38, 0xa1, 0x60, 0xff, 0x70, 0x91, 0x1e, 0x55, 0x09, 0xaa, 0x71, 0x83, 0x5b, 0x0f, 0xef, + 0x06, 0x2f, 0x3c, 0xac, 0x1b, 0x7c, 0x1b, 0xa6, 0x1a, 0x9a, 0x72, 0x2b, 0x99, 0xc9, 0xcb, 0x3d, + 0x17, 0x89, 0xa6, 0x07, 0xe3, 0xb2, 0x90, 0x65, 0x93, 0x08, 0x4e, 0x53, 0x45, 0xdf, 0x0a, 0xe3, + 0x7c, 0x9e, 0x45, 0x2b, 0xdc, 0x62, 0xe1, 0x63, 0xf9, 0xeb, 0x45, 0x6f, 0x82, 0xad, 0xc4, 0xba, + 0x56, 0x1d, 0x1b, 0xc4, 0xec, 0x3f, 0xb5, 0x00, 0xad, 0xb4, 0x77, 0x48, 0x8b, 0x84, 0x4e, 0x33, + 0x91, 0x51, 0xff, 0xbf, 0x16, 0xcc, 0x92, 0xae, 0xe2, 0xe5, 0xa0, 0xd5, 0x12, 0x4f, 0x8b, 0x9c, + 0xd7, 0xef, 0x4a, 0x4e, 0x1d, 0x65, 0xbe, 0x3f, 0x9b, 0x87, 0x81, 0x73, 0xdb, 0x43, 0x6b, 0x70, + 0x8a, 0x5f, 0x79, 0x0a, 0xa0, 0xd9, 0x28, 0x3f, 0x2a, 0x08, 0x9f, 0xda, 0xe8, 0x46, 0xc1, 0x59, + 0xf5, 0xec, 0xaf, 0x8c, 0x41, 0x6e, 0x2f, 0x3e, 0x14, 0xce, 0x7f, 0x28, 0x9c, 0xff, 0x50, 0x38, + 0xff, 0xa1, 0x70, 0xfe, 0x43, 0xe1, 0xfc, 0x07, 0x4d, 0x38, 0xff, 0xc7, 0x16, 0x9c, 0xea, 0x3e, + 0xb5, 0x4f, 0x82, 0x8f, 0xee, 0xc0, 0xa9, 0xee, 0xab, 0xa9, 0xa7, 0xf9, 0x58, 0x77, 0x3f, 0x93, + 0x6b, 0x2a, 0xe3, 0x1b, 0x70, 0x16, 0x7d, 0xfb, 0x97, 0x4a, 0x30, 0xbc, 0xb2, 0x47, 0xfc, 0xf8, + 0x04, 0x3e, 0xb1, 0x01, 0x93, 0x9e, 0xbf, 0x17, 0x34, 0xf7, 0x88, 0xcb, 0xe1, 0x47, 0x79, 0x9e, + 0x9e, 0x15, 0xa4, 0x27, 0xab, 0x06, 0x09, 0x9c, 0x22, 0xf9, 0x30, 0x64, 0xbf, 0x57, 0x61, 0x84, + 0x1f, 0xe6, 0x42, 0xf0, 0x9b, 0x79, 0x76, 0xb3, 0x41, 0x14, 0x57, 0x54, 0x22, 0x97, 0xe6, 0x97, + 0x85, 0xa8, 0x8e, 0xde, 0x81, 0xc9, 0x2d, 0x2f, 0x8c, 0xe2, 0x0d, 0xaf, 0x45, 0xa2, 0xd8, 0x69, + 0xb5, 0x1f, 0x40, 0xd6, 0xab, 0xc6, 0x61, 0xd5, 0xa0, 0x84, 0x53, 0x94, 0xd1, 0x36, 0x4c, 0x34, + 0x1d, 0xbd, 0xa9, 0xd1, 0x23, 0x37, 0xa5, 0x6e, 0x89, 0x1b, 0x3a, 0x21, 0x6c, 0xd2, 0xa5, 0xfb, + 0xb4, 0xc1, 0xc4, 0x95, 0x25, 0xf6, 0xd6, 0x57, 0xfb, 0x94, 0xcb, 0x29, 0x39, 0x8c, 0x32, 0x3c, + 0xcc, 0xa0, 0xb4, 0x6c, 0x32, 0x3c, 0x9a, 0xd9, 0xe8, 0x17, 0xa0, 0x4c, 0xe8, 0x10, 0x52, 0xc2, + 0xe2, 0xa2, 0xb9, 0x32, 0x58, 0x5f, 0xd7, 0xbc, 0x46, 0x18, 0x98, 0x52, 0xf6, 0x15, 0x49, 0x09, + 0x27, 0x44, 0xd1, 0x32, 0x8c, 0x44, 0x24, 0xf4, 0x48, 0x24, 0xae, 0x9c, 0x1e, 0xd3, 0xc8, 0xd0, + 0xb8, 0x2f, 0x06, 0xff, 0x8d, 0x45, 0x55, 0xba, 0xbc, 0x1c, 0x26, 0xa7, 0x64, 0xb7, 0x8c, 0xb6, + 0xbc, 0x16, 0x59, 0x29, 0x16, 0x50, 0xf4, 0x06, 0x8c, 0x86, 0xa4, 0xc9, 0xd4, 0x38, 0x13, 0x83, + 0x2f, 0x72, 0xae, 0x15, 0xe2, 0xf5, 0xb0, 0x24, 0x80, 0xae, 0x03, 0x0a, 0x09, 0x65, 0x98, 0x3c, + 0x7f, 0x5b, 0x99, 0x59, 0x8a, 0x13, 0x5c, 0xed, 0x78, 0x9c, 0x60, 0x48, 0xb7, 0x18, 0x9c, 0x51, + 0x0d, 0x5d, 0x85, 0x19, 0x55, 0x5a, 0xf5, 0xa3, 0xd8, 0xa1, 0x27, 0xe7, 0x14, 0xa3, 0xa5, 0xe4, + 0x15, 0x38, 0x8d, 0x80, 0xbb, 0xeb, 0xd8, 0x3f, 0x63, 0x01, 0x1f, 0xe7, 0x13, 0x78, 0xa5, 0xbf, + 0x6e, 0xbe, 0xd2, 0xcf, 0xe5, 0xce, 0x5c, 0xce, 0x0b, 0xfd, 0xbe, 0x05, 0x63, 0xda, 0xcc, 0x26, + 0x6b, 0xd6, 0xea, 0xb1, 0x66, 0x3b, 0x30, 0x4d, 0x57, 0xfa, 0xcd, 0xcd, 0x88, 0x84, 0x7b, 0xc4, + 0x65, 0x0b, 0xb3, 0xf0, 0x60, 0x0b, 0x53, 0xd9, 0x7f, 0xdd, 0x48, 0x11, 0xc4, 0x5d, 0x4d, 0xa0, + 0x97, 0xa5, 0x4e, 0xa3, 0x68, 0x98, 0x4f, 0x73, 0x7d, 0xc5, 0xe1, 0xc1, 0xfc, 0xb4, 0xf6, 0x21, + 0xba, 0x0e, 0xc3, 0xfe, 0x82, 0xfc, 0x46, 0x65, 0x67, 0xd7, 0x50, 0x8b, 0x25, 0x65, 0x67, 0xa7, + 0x96, 0x03, 0x4e, 0x70, 0xe8, 0x1e, 0xdd, 0x09, 0xa2, 0x38, 0x6d, 0x67, 0x77, 0x2d, 0x88, 0x62, + 0xcc, 0x20, 0xf6, 0x0b, 0x00, 0x2b, 0xf7, 0x48, 0x83, 0x2f, 0x75, 0xfd, 0xf5, 0x61, 0xe5, 0xbf, + 0x3e, 0xec, 0xff, 0x60, 0xc1, 0xe4, 0xea, 0xb2, 0x21, 0xc0, 0x5d, 0x00, 0xe0, 0x4f, 0xa6, 0x3b, + 0x77, 0xd6, 0xa5, 0xd6, 0x9b, 0x2b, 0x2e, 0x55, 0x29, 0xd6, 0x30, 0xd0, 0x39, 0x28, 0x36, 0x3b, + 0xbe, 0x10, 0x26, 0x8e, 0xd2, 0x0b, 0xfb, 0x46, 0xc7, 0xc7, 0xb4, 0x4c, 0xb3, 0xdd, 0x2f, 0x0e, + 0x6c, 0xbb, 0xdf, 0xd7, 0x87, 0x1e, 0xcd, 0xc3, 0xf0, 0xdd, 0xbb, 0x9e, 0xcb, 0x3d, 0x15, 0x85, + 0x46, 0xfe, 0xce, 0x9d, 0x6a, 0x25, 0xc2, 0xbc, 0xdc, 0xfe, 0x72, 0x11, 0xe6, 0x56, 0x9b, 0xe4, + 0xde, 0xfb, 0xf4, 0xd6, 0x1c, 0xd4, 0xf3, 0xe0, 0x68, 0x92, 0x9c, 0xa3, 0x7a, 0x97, 0xf4, 0x1f, + 0x8f, 0x2d, 0x18, 0xe5, 0x66, 0x66, 0xd2, 0x77, 0xf3, 0xd5, 0xac, 0xd6, 0xf3, 0x07, 0x64, 0x81, + 0x9b, 0xab, 0x09, 0xd7, 0x33, 0x75, 0xd3, 0x8a, 0x52, 0x2c, 0x89, 0xcf, 0x7d, 0x0a, 0xc6, 0x75, + 0xcc, 0x23, 0xf9, 0x79, 0xfd, 0x3f, 0x45, 0x98, 0xa6, 0x3d, 0x78, 0xa8, 0x13, 0x71, 0xab, 0x7b, + 0x22, 0x8e, 0xdb, 0xd7, 0xa7, 0xff, 0x6c, 0xbc, 0x9d, 0x9e, 0x8d, 0xe7, 0xf2, 0x66, 0xe3, 0xa4, + 0xe7, 0xe0, 0xbb, 0x2c, 0x38, 0xb5, 0xda, 0x0c, 0x1a, 0xbb, 0x29, 0x7f, 0x9c, 0x97, 0x60, 0x8c, + 0x9e, 0xe3, 0x91, 0xe1, 0x2a, 0x6e, 0x04, 0x0f, 0x10, 0x20, 0xac, 0xe3, 0x69, 0xd5, 0x6e, 0xdd, + 0xaa, 0x56, 0xb2, 0x62, 0x0e, 0x08, 0x10, 0xd6, 0xf1, 0xec, 0xdf, 0xb2, 0xe0, 0xfc, 0xd5, 0xe5, + 0x95, 0x64, 0x29, 0x76, 0x85, 0x3d, 0xb8, 0x04, 0x23, 0x6d, 0x57, 0xeb, 0x4a, 0x22, 0x9f, 0xad, + 0xb0, 0x5e, 0x08, 0xe8, 0x07, 0x25, 0xa4, 0xc7, 0x4f, 0x5b, 0x70, 0xea, 0xaa, 0x17, 0xd3, 0x6b, + 0x39, 0xed, 0x80, 0x4f, 0xef, 0xe5, 0xc8, 0x8b, 0x83, 0x70, 0x3f, 0xed, 0x80, 0x8f, 0x15, 0x04, + 0x6b, 0x58, 0xbc, 0xe5, 0x3d, 0x8f, 0x19, 0x38, 0x17, 0x4c, 0xb5, 0x13, 0x16, 0xe5, 0x58, 0x61, + 0xd0, 0x0f, 0x73, 0xbd, 0x90, 0x09, 0xf9, 0xf6, 0xc5, 0x09, 0xab, 0x3e, 0xac, 0x22, 0x01, 0x38, + 0xc1, 0xa1, 0x0f, 0xa8, 0xf9, 0xab, 0xcd, 0x4e, 0x14, 0x93, 0x70, 0x2b, 0xca, 0x39, 0x1d, 0x5f, + 0x80, 0x32, 0x91, 0x22, 0x75, 0xd1, 0x6b, 0xc5, 0x6a, 0x2a, 0x59, 0x3b, 0x8f, 0x03, 0xa0, 0xf0, + 0x06, 0xf0, 0xee, 0x3b, 0x9a, 0x7b, 0xd6, 0x2a, 0x20, 0xa2, 0xb7, 0xa5, 0x07, 0x46, 0x60, 0x1e, + 0xd6, 0x2b, 0x5d, 0x50, 0x9c, 0x51, 0xc3, 0xfe, 0x31, 0x0b, 0xce, 0xa8, 0x0f, 0xfe, 0xc0, 0x7d, + 0xa6, 0xfd, 0x95, 0x02, 0x4c, 0x5c, 0xdb, 0xd8, 0xa8, 0x5d, 0x25, 0xb1, 0xb8, 0xb6, 0xfb, 0x6b, + 0xbd, 0xb1, 0xa6, 0xbc, 0xeb, 0xf5, 0x0a, 0xec, 0xc4, 0x5e, 0x73, 0x81, 0xc7, 0xd7, 0x59, 0xa8, + 0xfa, 0xf1, 0xcd, 0xb0, 0x1e, 0x87, 0x9e, 0xbf, 0x9d, 0xa9, 0xee, 0x93, 0xcc, 0x45, 0x31, 0x8f, + 0xb9, 0x40, 0x2f, 0xc0, 0x08, 0x0b, 0xf0, 0x23, 0x27, 0xe1, 0x51, 0xf5, 0x88, 0x62, 0xa5, 0x87, + 0x07, 0xf3, 0xe5, 0x5b, 0xb8, 0xca, 0xff, 0x60, 0x81, 0x8a, 0x6e, 0xc1, 0xd8, 0x4e, 0x1c, 0xb7, + 0xaf, 0x11, 0xc7, 0xa5, 0xaf, 0x65, 0x7e, 0x1c, 0x5e, 0xc8, 0x3a, 0x0e, 0xe9, 0x20, 0x70, 0xb4, + 0xe4, 0x04, 0x49, 0xca, 0x22, 0xac, 0xd3, 0xb1, 0xeb, 0x00, 0x09, 0xec, 0x98, 0x54, 0x1d, 0xf6, + 0x1f, 0x58, 0x30, 0xca, 0x63, 0x2d, 0x84, 0xe8, 0x35, 0x18, 0x22, 0xf7, 0x48, 0x43, 0xb0, 0xca, + 0x99, 0x1d, 0x4e, 0x38, 0x2d, 0x2e, 0xb2, 0xa5, 0xff, 0x31, 0xab, 0x85, 0xae, 0xc1, 0x28, 0xed, + 0xed, 0x55, 0x15, 0x78, 0xe2, 0xf1, 0xbc, 0x2f, 0x56, 0xd3, 0xce, 0x99, 0x33, 0x51, 0x84, 0x65, + 0x75, 0xa6, 0x2c, 0x6e, 0xb4, 0xeb, 0xf4, 0xc4, 0x8e, 0x7b, 0x31, 0x16, 0x1b, 0xcb, 0x35, 0x8e, + 0x24, 0xa8, 0x71, 0x65, 0xb1, 0x2c, 0xc4, 0x09, 0x11, 0x7b, 0x03, 0xca, 0x74, 0x52, 0x17, 0x9b, + 0x9e, 0xd3, 0x5b, 0xff, 0xfd, 0x34, 0x94, 0xa5, 0x76, 0x3b, 0x12, 0x3e, 0xd6, 0x8c, 0xaa, 0x54, + 0x7e, 0x47, 0x38, 0x81, 0xdb, 0x5b, 0x70, 0x9a, 0x19, 0x21, 0x3a, 0xf1, 0x8e, 0xb1, 0xc7, 0xfa, + 0x2f, 0xe6, 0x67, 0xc4, 0xcb, 0x93, 0xcf, 0xcc, 0xac, 0xe6, 0xc6, 0x38, 0x2e, 0x29, 0x26, 0xaf, + 0x50, 0xfb, 0x8f, 0x86, 0xe0, 0xd1, 0x6a, 0x3d, 0x3f, 0x0c, 0xc7, 0x2b, 0x30, 0xce, 0xf9, 0x52, + 0xba, 0xb4, 0x9d, 0xa6, 0x68, 0x57, 0xc9, 0x6a, 0x37, 0x34, 0x18, 0x36, 0x30, 0xd1, 0x79, 0x28, + 0x7a, 0xef, 0xfa, 0x69, 0x8f, 0xa0, 0xea, 0x9b, 0xeb, 0x98, 0x96, 0x53, 0x30, 0x65, 0x71, 0xf9, + 0xdd, 0xa1, 0xc0, 0x8a, 0xcd, 0x7d, 0x1d, 0x26, 0xbd, 0xa8, 0x11, 0x79, 0x55, 0x9f, 0x9e, 0x33, + 0xda, 0x49, 0xa5, 0xa4, 0x22, 0xb4, 0xd3, 0x0a, 0x8a, 0x53, 0xd8, 0xda, 0x45, 0x36, 0x3c, 0x30, + 0x9b, 0xdc, 0xd7, 0xe9, 0x98, 0xbe, 0x00, 0xda, 0xec, 0xeb, 0x22, 0x26, 0x74, 0x17, 0x2f, 0x00, + 0xfe, 0xc1, 0x11, 0x96, 0x30, 0xfa, 0xe4, 0x6c, 0xec, 0x38, 0xed, 0xc5, 0x4e, 0xbc, 0x53, 0xf1, + 0xa2, 0x46, 0xb0, 0x47, 0xc2, 0x7d, 0x26, 0x2d, 0x28, 0x25, 0x4f, 0x4e, 0x05, 0x58, 0xbe, 0xb6, + 0x58, 0xa3, 0x98, 0xb8, 0xbb, 0x0e, 0x5a, 0x84, 0x29, 0x59, 0x58, 0x27, 0x11, 0xbb, 0xc2, 0xc6, + 0x18, 0x19, 0xe5, 0xa3, 0x23, 0x8a, 0x15, 0x91, 0x34, 0xbe, 0xc9, 0x49, 0xc3, 0x71, 0x70, 0xd2, + 0x2f, 0xc3, 0x84, 0xe7, 0x7b, 0xb1, 0xe7, 0xc4, 0x01, 0xd7, 0x18, 0x71, 0xc1, 0x00, 0x13, 0x85, + 0x57, 0x75, 0x00, 0x36, 0xf1, 0xec, 0xff, 0x3a, 0x04, 0x33, 0x6c, 0xda, 0x3e, 0x5c, 0x61, 0xdf, + 0x48, 0x2b, 0xec, 0x56, 0xf7, 0x0a, 0x3b, 0x8e, 0x27, 0xc2, 0x03, 0x2f, 0xb3, 0x77, 0xa0, 0xac, + 0xdc, 0x92, 0xa4, 0x5f, 0xa2, 0x95, 0xe3, 0x97, 0xd8, 0x9f, 0xfb, 0x90, 0x16, 0x65, 0xc5, 0x4c, + 0x8b, 0xb2, 0xbf, 0x65, 0x41, 0xa2, 0x53, 0x41, 0xd7, 0xa0, 0xdc, 0x0e, 0x98, 0x05, 0x64, 0x28, + 0xcd, 0x8a, 0x1f, 0xcd, 0xbc, 0xa8, 0xf8, 0xa5, 0xc8, 0x3f, 0xbe, 0x26, 0x6b, 0xe0, 0xa4, 0x32, + 0x5a, 0x82, 0xd1, 0x76, 0x48, 0xea, 0x31, 0x8b, 0xc6, 0xd1, 0x97, 0x0e, 0x5f, 0x23, 0x1c, 0x1f, + 0xcb, 0x8a, 0xf6, 0x2f, 0x58, 0x00, 0xdc, 0x68, 0xcb, 0xf1, 0xb7, 0xc9, 0x09, 0x88, 0xbb, 0x2b, + 0x30, 0x14, 0xb5, 0x49, 0xa3, 0x97, 0x6d, 0x6a, 0xd2, 0x9f, 0x7a, 0x9b, 0x34, 0x92, 0x01, 0xa7, + 0xff, 0x30, 0xab, 0x6d, 0x7f, 0x0f, 0xc0, 0x64, 0x82, 0x56, 0x8d, 0x49, 0x0b, 0x3d, 0x6b, 0x78, + 0xe7, 0x9f, 0x4b, 0x79, 0xe7, 0x97, 0x19, 0xb6, 0x26, 0x59, 0x7d, 0x07, 0x8a, 0x2d, 0xe7, 0x9e, + 0x10, 0x9d, 0x3d, 0xdd, 0xbb, 0x1b, 0x94, 0xfe, 0xc2, 0x9a, 0x73, 0x8f, 0x3f, 0x12, 0x9f, 0x96, + 0x0b, 0x64, 0xcd, 0xb9, 0x77, 0xc8, 0x2d, 0x50, 0xd9, 0x21, 0x75, 0xc3, 0x8b, 0xe2, 0x2f, 0xfe, + 0x97, 0xe4, 0x3f, 0x5b, 0x76, 0xb4, 0x11, 0xd6, 0x96, 0xe7, 0x0b, 0x13, 0xa6, 0x81, 0xda, 0xf2, + 0xfc, 0x74, 0x5b, 0x9e, 0x3f, 0x40, 0x5b, 0x9e, 0x8f, 0xde, 0x83, 0x51, 0x61, 0x2e, 0x28, 0xa2, + 0xe1, 0x5c, 0x19, 0xa0, 0x3d, 0x61, 0x6d, 0xc8, 0xdb, 0xbc, 0x22, 0x1f, 0xc1, 0xa2, 0xb4, 0x6f, + 0xbb, 0xb2, 0x41, 0xf4, 0xd7, 0x2d, 0x98, 0x14, 0xbf, 0x31, 0x79, 0xb7, 0x43, 0xa2, 0x58, 0xf0, + 0x9e, 0x9f, 0x1c, 0xbc, 0x0f, 0xa2, 0x22, 0xef, 0xca, 0x27, 0xe5, 0x31, 0x6b, 0x02, 0xfb, 0xf6, + 0x28, 0xd5, 0x0b, 0xf4, 0x0f, 0x2c, 0x38, 0xdd, 0x72, 0xee, 0xf1, 0x16, 0x79, 0x19, 0x76, 0x62, + 0x2f, 0x10, 0x9a, 0xfa, 0xd7, 0x06, 0x9b, 0xfe, 0xae, 0xea, 0xbc, 0x93, 0x52, 0x3f, 0x79, 0x3a, + 0x0b, 0xa5, 0x6f, 0x57, 0x33, 0xfb, 0x35, 0xb7, 0x05, 0x25, 0xb9, 0xde, 0x32, 0x44, 0x0d, 0x15, + 0x9d, 0xb1, 0x3e, 0xb2, 0xb5, 0xa6, 0xee, 0x22, 0x4f, 0xdb, 0x11, 0x6b, 0xed, 0xa1, 0xb6, 0xf3, + 0x0e, 0x8c, 0xeb, 0x6b, 0xec, 0xa1, 0xb6, 0xf5, 0x2e, 0x9c, 0xca, 0x58, 0x4b, 0x0f, 0xb5, 0xc9, + 0xbb, 0x70, 0x2e, 0x77, 0x7d, 0x3c, 0xcc, 0x86, 0xed, 0xaf, 0x58, 0xfa, 0x39, 0x78, 0x02, 0x3a, + 0x87, 0x65, 0x53, 0xe7, 0x70, 0xa1, 0xf7, 0xce, 0xc9, 0x51, 0x3c, 0xbc, 0xad, 0x77, 0x9a, 0x9e, + 0xea, 0xe8, 0x0d, 0x18, 0x69, 0xd2, 0x12, 0x69, 0xa7, 0x6a, 0xf7, 0xdf, 0x91, 0x09, 0x2f, 0xc5, + 0xca, 0x23, 0x2c, 0x28, 0xd8, 0xbf, 0x6c, 0xc1, 0xd0, 0x09, 0x8c, 0x04, 0x36, 0x47, 0xe2, 0xd9, + 0x5c, 0xd2, 0x22, 0x50, 0xef, 0x02, 0x76, 0xee, 0xae, 0xdc, 0x8b, 0x89, 0x1f, 0xb1, 0xa7, 0x62, + 0xe6, 0xc0, 0x7c, 0x1b, 0x9c, 0xba, 0x11, 0x38, 0xee, 0x92, 0xd3, 0x74, 0xfc, 0x06, 0x09, 0xab, + 0xfe, 0xf6, 0x91, 0x0c, 0xa6, 0x0b, 0xfd, 0x0c, 0xa6, 0xed, 0x1d, 0x40, 0x7a, 0x03, 0xc2, 0xa5, + 0x04, 0xc3, 0xa8, 0xc7, 0x9b, 0x12, 0xc3, 0xff, 0x64, 0x36, 0x6b, 0xd6, 0xd5, 0x33, 0xcd, 0x59, + 0x82, 0x17, 0x60, 0x49, 0xc8, 0x7e, 0x05, 0x32, 0xdd, 0xc8, 0xfb, 0x8b, 0x0d, 0xec, 0xcf, 0xc2, + 0x0c, 0xab, 0x79, 0xc4, 0x27, 0xad, 0x9d, 0x92, 0x4a, 0x66, 0xc4, 0x8c, 0xb3, 0xbf, 0x64, 0xc1, + 0xd4, 0x7a, 0x2a, 0x94, 0xd6, 0x25, 0xa6, 0x00, 0xcd, 0x10, 0x86, 0xd7, 0x59, 0x29, 0x16, 0xd0, + 0x63, 0x97, 0x41, 0xfd, 0xa5, 0x05, 0x49, 0x64, 0x87, 0x13, 0x60, 0xbc, 0x96, 0x0d, 0xc6, 0x2b, + 0x53, 0x36, 0xa2, 0xba, 0x93, 0xc7, 0x77, 0xa1, 0xeb, 0x2a, 0x8c, 0x51, 0x0f, 0xb1, 0x48, 0x42, + 0x86, 0x07, 0xbd, 0x99, 0x34, 0x63, 0x1d, 0xc9, 0xc0, 0x46, 0xcc, 0xaa, 0x59, 0xe1, 0x7e, 0x40, + 0xac, 0x9a, 0x55, 0x7f, 0x72, 0x76, 0x68, 0x4d, 0xeb, 0x32, 0x3b, 0xb9, 0xbe, 0x99, 0x79, 0xa9, + 0x39, 0x4d, 0xef, 0x3d, 0xa2, 0x62, 0xb1, 0xcd, 0x0b, 0xaf, 0x33, 0x51, 0x7a, 0x78, 0x30, 0x3f, + 0xa1, 0xfe, 0xf1, 0xd8, 0xaf, 0x49, 0x15, 0xfb, 0x1a, 0x4c, 0xa5, 0x06, 0x0c, 0xbd, 0x04, 0xc3, + 0xed, 0x1d, 0x27, 0x22, 0x29, 0x4f, 0x8e, 0xe1, 0x1a, 0x2d, 0x3c, 0x3c, 0x98, 0x9f, 0x54, 0x15, + 0x58, 0x09, 0xe6, 0xd8, 0xf6, 0x9f, 0x5a, 0x30, 0xb4, 0x1e, 0xb8, 0x27, 0xb1, 0x98, 0x5e, 0x37, + 0x16, 0xd3, 0x63, 0x79, 0x91, 0xb3, 0x73, 0xd7, 0xd1, 0x6a, 0x6a, 0x1d, 0x5d, 0xc8, 0xa5, 0xd0, + 0x7b, 0x09, 0xb5, 0x60, 0x8c, 0xc5, 0xe3, 0x16, 0x9e, 0x25, 0x2f, 0x18, 0x6f, 0x80, 0xf9, 0xd4, + 0x1b, 0x60, 0x4a, 0x43, 0xd5, 0x5e, 0x02, 0x4f, 0xc1, 0xa8, 0xf0, 0x6e, 0x48, 0xfb, 0xe3, 0x09, + 0x5c, 0x2c, 0xe1, 0xf6, 0x8f, 0x17, 0xc1, 0x88, 0xff, 0x8d, 0x7e, 0xd5, 0x82, 0x85, 0x90, 0x5b, + 0x3d, 0xba, 0x95, 0x4e, 0xe8, 0xf9, 0xdb, 0xf5, 0xc6, 0x0e, 0x71, 0x3b, 0x4d, 0xcf, 0xdf, 0xae, + 0x6e, 0xfb, 0x81, 0x2a, 0x5e, 0xb9, 0x47, 0x1a, 0x1d, 0xa6, 0x08, 0xe9, 0x13, 0x6c, 0x5c, 0x59, + 0x0f, 0x3f, 0x7f, 0xff, 0x60, 0x7e, 0x01, 0x1f, 0x89, 0x36, 0x3e, 0x62, 0x5f, 0xd0, 0x6f, 0x59, + 0x70, 0x85, 0x87, 0xc5, 0x1e, 0xbc, 0xff, 0x3d, 0x5e, 0x4c, 0x35, 0x49, 0x2a, 0x21, 0xb2, 0x41, + 0xc2, 0xd6, 0xd2, 0xcb, 0x62, 0x40, 0xaf, 0xd4, 0x8e, 0xd6, 0x16, 0x3e, 0x6a, 0xe7, 0xec, 0x7f, + 0x51, 0x84, 0x09, 0x11, 0x5b, 0x47, 0x04, 0x6d, 0x7b, 0xc9, 0x58, 0x12, 0x8f, 0xa7, 0x96, 0xc4, + 0x8c, 0x81, 0x7c, 0x3c, 0xf1, 0xda, 0x22, 0x98, 0x69, 0x3a, 0x51, 0x7c, 0x8d, 0x38, 0x61, 0xbc, + 0x49, 0x1c, 0x6e, 0xbb, 0x53, 0x3c, 0xb2, 0x9d, 0x91, 0x12, 0xd1, 0xdc, 0x48, 0x13, 0xc3, 0xdd, + 0xf4, 0xd1, 0x1e, 0x20, 0x66, 0x80, 0x14, 0x3a, 0x7e, 0xc4, 0xbf, 0xc5, 0x13, 0x3a, 0x83, 0xa3, + 0xb5, 0x3a, 0x27, 0x5a, 0x45, 0x37, 0xba, 0xa8, 0xe1, 0x8c, 0x16, 0x34, 0xc3, 0xb2, 0xe1, 0x41, + 0x0d, 0xcb, 0x46, 0xfa, 0x38, 0xbd, 0xfa, 0x30, 0xdd, 0x15, 0x1e, 0xe9, 0x2d, 0x28, 0x2b, 0xd3, + 0x7c, 0x71, 0xe8, 0xf4, 0x8e, 0x32, 0x96, 0xa6, 0xc0, 0xc5, 0x28, 0x89, 0x5b, 0x48, 0x42, 0xce, + 0xfe, 0x87, 0x05, 0xa3, 0x41, 0x3e, 0x89, 0xeb, 0x50, 0x72, 0xa2, 0xc8, 0xdb, 0xf6, 0x89, 0x2b, + 0x76, 0xec, 0x47, 0xf3, 0x76, 0xac, 0xd1, 0x0c, 0x73, 0x8f, 0x58, 0x14, 0x35, 0xb1, 0xa2, 0x81, + 0xae, 0x71, 0x0b, 0xa9, 0x3d, 0xc9, 0xf3, 0x0f, 0x46, 0x0d, 0xa4, 0x0d, 0xd5, 0x1e, 0xc1, 0xa2, + 0x3e, 0xfa, 0x1c, 0x37, 0x61, 0xbb, 0xee, 0x07, 0x77, 0xfd, 0xab, 0x41, 0x20, 0x1d, 0xe2, 0x07, + 0x23, 0x38, 0x23, 0x0d, 0xd7, 0x54, 0x75, 0x6c, 0x52, 0x1b, 0x2c, 0x84, 0xe0, 0xb7, 0xc3, 0x29, + 0x4a, 0xda, 0x74, 0x6b, 0x8d, 0x10, 0x81, 0x29, 0x11, 0xb8, 0x49, 0x96, 0x89, 0xb1, 0xcb, 0x64, + 0xe7, 0xcd, 0xda, 0x89, 0x2c, 0xf1, 0xba, 0x49, 0x02, 0xa7, 0x69, 0xda, 0x3f, 0x65, 0x01, 0x73, + 0xf1, 0x3b, 0x01, 0x96, 0xe1, 0xd3, 0x26, 0xcb, 0x30, 0x9b, 0x37, 0xc8, 0x39, 0xdc, 0xc2, 0x8b, + 0x7c, 0x65, 0xd5, 0xc2, 0xe0, 0xde, 0xbe, 0x30, 0x1f, 0xe8, 0xcf, 0xc9, 0xda, 0xff, 0xcb, 0xe2, + 0x87, 0x98, 0x32, 0x9c, 0x47, 0xdf, 0x01, 0xa5, 0x86, 0xd3, 0x76, 0x1a, 0x3c, 0x59, 0x45, 0xae, + 0x54, 0xc7, 0xa8, 0xb4, 0xb0, 0x2c, 0x6a, 0x70, 0x29, 0x85, 0x0c, 0x00, 0x56, 0x92, 0xc5, 0x7d, + 0x25, 0x13, 0xaa, 0xc9, 0xb9, 0x5d, 0x98, 0x30, 0x88, 0x3d, 0xd4, 0x27, 0xed, 0x77, 0xf0, 0x2b, + 0x56, 0x05, 0xac, 0x6b, 0xc1, 0x8c, 0xaf, 0xfd, 0xa7, 0x17, 0x8a, 0x7c, 0xa6, 0x7c, 0xb4, 0xdf, + 0x25, 0xca, 0x6e, 0x1f, 0xcd, 0xe1, 0x30, 0x45, 0x06, 0x77, 0x53, 0xb6, 0x7f, 0xc2, 0x82, 0x47, + 0x74, 0x44, 0xcd, 0xa7, 0xa1, 0x9f, 0x9c, 0xb8, 0x02, 0xa5, 0xa0, 0x4d, 0x42, 0x27, 0x0e, 0x42, + 0x71, 0x6b, 0x5c, 0x96, 0x83, 0x7e, 0x53, 0x94, 0x1f, 0x8a, 0x50, 0xcf, 0x92, 0xba, 0x2c, 0xc7, + 0xaa, 0x26, 0x7d, 0xc7, 0xb0, 0xc1, 0x88, 0x84, 0xf7, 0x0a, 0x3b, 0x03, 0x98, 0xca, 0x34, 0xc2, + 0x02, 0x62, 0xff, 0x91, 0xc5, 0x17, 0x96, 0xde, 0x75, 0xf4, 0x2e, 0x4c, 0xb7, 0x9c, 0xb8, 0xb1, + 0xb3, 0x72, 0xaf, 0x1d, 0x72, 0xa9, 0xbb, 0x1c, 0xa7, 0xa7, 0xfb, 0x8d, 0x93, 0xf6, 0x91, 0x89, + 0x55, 0xde, 0x5a, 0x8a, 0x18, 0xee, 0x22, 0x8f, 0x36, 0x61, 0x8c, 0x95, 0x31, 0xc7, 0xac, 0xa8, + 0x17, 0x6b, 0x90, 0xd7, 0x9a, 0xd2, 0x3a, 0xaf, 0x25, 0x74, 0xb0, 0x4e, 0xd4, 0xfe, 0xb9, 0x22, + 0xdf, 0xed, 0x8c, 0xdb, 0x7e, 0x0a, 0x46, 0xdb, 0x81, 0xbb, 0x5c, 0xad, 0x60, 0x31, 0x0b, 0xea, + 0x1a, 0xa9, 0xf1, 0x62, 0x2c, 0xe1, 0xe8, 0x32, 0x94, 0xc4, 0x4f, 0xa9, 0x25, 0x61, 0x67, 0xb3, + 0xc0, 0x8b, 0xb0, 0x82, 0xa2, 0xe7, 0x01, 0xda, 0x61, 0xb0, 0xe7, 0xb9, 0xcc, 0xad, 0xbf, 0x68, + 0x1a, 0x8c, 0xd4, 0x14, 0x04, 0x6b, 0x58, 0xe8, 0x55, 0x98, 0xe8, 0xf8, 0x11, 0x67, 0x47, 0x9c, + 0x4d, 0x11, 0x15, 0xb9, 0x94, 0x98, 0x32, 0xdc, 0xd2, 0x81, 0xd8, 0xc4, 0x45, 0x8b, 0x30, 0x12, + 0x3b, 0xcc, 0x00, 0x62, 0x38, 0xdf, 0x72, 0x73, 0x83, 0x62, 0xe8, 0x79, 0x11, 0x68, 0x05, 0x2c, + 0x2a, 0xa2, 0xb7, 0xa4, 0x8f, 0x24, 0x3f, 0xd8, 0x85, 0xc9, 0xf4, 0x60, 0x97, 0x80, 0xe6, 0x21, + 0x29, 0x4c, 0xb1, 0x0d, 0x5a, 0xe8, 0x55, 0x00, 0x72, 0x2f, 0x26, 0xa1, 0xef, 0x34, 0x95, 0x7d, + 0x91, 0xb2, 0xa8, 0xad, 0x04, 0xeb, 0x41, 0x7c, 0x2b, 0x22, 0xdf, 0xb6, 0xa2, 0x50, 0xb0, 0x86, + 0x6e, 0xff, 0x56, 0x19, 0x20, 0x61, 0xdc, 0xd1, 0x7b, 0x5d, 0x27, 0xd7, 0x33, 0xbd, 0x59, 0xfd, + 0xe3, 0x3b, 0xb6, 0xd0, 0xf7, 0x5a, 0x30, 0xe6, 0x34, 0x9b, 0x41, 0xc3, 0x89, 0xd9, 0x14, 0x15, + 0x7a, 0x9f, 0x9c, 0xa2, 0xfd, 0xc5, 0xa4, 0x06, 0xef, 0xc2, 0x0b, 0x72, 0x89, 0x6a, 0x90, 0xbe, + 0xbd, 0xd0, 0x1b, 0x46, 0x9f, 0x90, 0xef, 0x39, 0xbe, 0xb6, 0xe6, 0xd2, 0xef, 0xb9, 0x32, 0xbb, + 0x24, 0xb4, 0xa7, 0x1c, 0xba, 0x65, 0x44, 0xcb, 0x1d, 0xca, 0xf7, 0x02, 0x33, 0xf8, 0xd7, 0x7e, + 0x81, 0x72, 0x51, 0x4d, 0xf7, 0x08, 0x1f, 0xce, 0x77, 0xb9, 0xd2, 0x1e, 0x4a, 0x7d, 0xbc, 0xc1, + 0xdf, 0x81, 0x29, 0xd7, 0xe4, 0x02, 0xc4, 0x52, 0x7c, 0x32, 0x8f, 0x6e, 0x8a, 0x69, 0x48, 0xee, + 0xfd, 0x14, 0x00, 0xa7, 0x09, 0xa3, 0x1a, 0xf7, 0xf6, 0xaf, 0xfa, 0x5b, 0x81, 0xb0, 0xdb, 0xb7, + 0x73, 0xe7, 0x72, 0x3f, 0x8a, 0x49, 0x8b, 0x62, 0x26, 0xd7, 0xfb, 0xba, 0xa8, 0x8b, 0x15, 0x15, + 0xf4, 0x06, 0x8c, 0x30, 0x27, 0x9e, 0x68, 0xb6, 0x94, 0x2f, 0x76, 0x34, 0xe3, 0x52, 0x25, 0x3b, + 0x92, 0xfd, 0x8d, 0xb0, 0xa0, 0x80, 0xae, 0x49, 0x8f, 0xb6, 0xa8, 0xea, 0xdf, 0x8a, 0x08, 0xf3, + 0x68, 0x2b, 0x2f, 0x7d, 0x34, 0x71, 0x56, 0xe3, 0xe5, 0x99, 0xe9, 0x93, 0x8c, 0x9a, 0x94, 0x8d, + 0x12, 0xff, 0x65, 0x56, 0xa6, 0x59, 0xc8, 0xef, 0x9e, 0x99, 0xb9, 0x29, 0x19, 0xce, 0xdb, 0x26, + 0x09, 0x9c, 0xa6, 0x49, 0x59, 0x52, 0xbe, 0xed, 0x85, 0xe5, 0x7f, 0xbf, 0xc3, 0x83, 0xbf, 0xc4, + 0xd9, 0x75, 0xc4, 0x4b, 0xb0, 0xa8, 0x7f, 0xa2, 0xfc, 0xc1, 0x9c, 0x0f, 0xd3, 0xe9, 0x2d, 0xfa, + 0x50, 0xf9, 0x91, 0x3f, 0x18, 0x82, 0x49, 0x73, 0x49, 0xa1, 0x2b, 0x50, 0x16, 0x44, 0x54, 0x24, + 0x75, 0xb5, 0x4b, 0xd6, 0x24, 0x00, 0x27, 0x38, 0x2c, 0x80, 0x3e, 0xab, 0xae, 0x59, 0x6c, 0x26, + 0x01, 0xf4, 0x15, 0x04, 0x6b, 0x58, 0xf4, 0x65, 0xb5, 0x19, 0x04, 0xb1, 0xba, 0x91, 0xd4, 0xba, + 0x5b, 0x62, 0xa5, 0x58, 0x40, 0xe9, 0x4d, 0xb4, 0x4b, 0x42, 0x9f, 0x34, 0xcd, 0x00, 0xad, 0xea, + 0x26, 0xba, 0xae, 0x03, 0xb1, 0x89, 0x4b, 0xef, 0xd3, 0x20, 0x62, 0x0b, 0x59, 0xbc, 0xdf, 0x12, + 0x0b, 0xd8, 0x3a, 0x77, 0xaa, 0x95, 0x70, 0xf4, 0x59, 0x78, 0x44, 0x45, 0xb5, 0xc1, 0x5c, 0xa4, + 0x2d, 0x5b, 0x1c, 0x31, 0xc4, 0x2d, 0x8f, 0x2c, 0x67, 0xa3, 0xe1, 0xbc, 0xfa, 0xe8, 0x75, 0x98, + 0x14, 0x3c, 0xbe, 0xa4, 0x38, 0x6a, 0x5a, 0x59, 0x5c, 0x37, 0xa0, 0x38, 0x85, 0x2d, 0x43, 0xcc, + 0x32, 0x36, 0x5b, 0x52, 0x28, 0x75, 0x87, 0x98, 0xd5, 0xe1, 0xb8, 0xab, 0x06, 0x5a, 0x84, 0x29, + 0xce, 0x84, 0x79, 0xfe, 0x36, 0x9f, 0x13, 0xe1, 0x98, 0xa3, 0xb6, 0xd4, 0x4d, 0x13, 0x8c, 0xd3, + 0xf8, 0xe8, 0x15, 0x18, 0x77, 0xc2, 0xc6, 0x8e, 0x17, 0x93, 0x46, 0xdc, 0x09, 0xb9, 0xc7, 0x8e, + 0x66, 0xa6, 0xb2, 0xa8, 0xc1, 0xb0, 0x81, 0x69, 0xbf, 0x07, 0xa7, 0x32, 0xbc, 0xed, 0xe9, 0xc2, + 0x71, 0xda, 0x9e, 0xfc, 0xa6, 0x94, 0x2d, 0xeb, 0x62, 0xad, 0x2a, 0xbf, 0x46, 0xc3, 0xa2, 0xab, + 0x93, 0x79, 0xe5, 0x6b, 0x49, 0xd8, 0xd4, 0xea, 0x5c, 0x95, 0x00, 0x9c, 0xe0, 0xd8, 0xff, 0xa3, + 0x00, 0x53, 0x19, 0x62, 0x7a, 0x96, 0x08, 0x2c, 0xf5, 0x4a, 0x49, 0xf2, 0x7e, 0x99, 0x11, 0x8b, + 0x0b, 0x47, 0x88, 0x58, 0x5c, 0xec, 0x17, 0xb1, 0x78, 0xe8, 0xfd, 0x44, 0x2c, 0x36, 0x47, 0x6c, + 0x78, 0xa0, 0x11, 0xcb, 0x88, 0x72, 0x3c, 0x72, 0xc4, 0x28, 0xc7, 0xc6, 0xa0, 0x8f, 0x0e, 0x30, + 0xe8, 0x3f, 0x5c, 0x80, 0xe9, 0xb4, 0x39, 0xdd, 0x09, 0x08, 0x6e, 0xdf, 0x30, 0x04, 0xb7, 0xd9, + 0x69, 0xf5, 0xd2, 0x46, 0x7e, 0x79, 0x42, 0x5c, 0x9c, 0x12, 0xe2, 0x7e, 0x7c, 0x20, 0x6a, 0xbd, + 0x05, 0xba, 0x7f, 0xa7, 0x00, 0x67, 0xd2, 0x55, 0x96, 0x9b, 0x8e, 0xd7, 0x3a, 0x81, 0xb1, 0xb9, + 0x69, 0x8c, 0xcd, 0xb3, 0x83, 0x7c, 0x0d, 0xeb, 0x5a, 0xee, 0x00, 0xdd, 0x49, 0x0d, 0xd0, 0x95, + 0xc1, 0x49, 0xf6, 0x1e, 0xa5, 0xaf, 0x15, 0xe1, 0x42, 0x66, 0xbd, 0x44, 0xee, 0xb9, 0x6a, 0xc8, + 0x3d, 0x9f, 0x4f, 0xc9, 0x3d, 0xed, 0xde, 0xb5, 0x8f, 0x47, 0x10, 0x2a, 0x9c, 0x2d, 0x99, 0x2f, + 0xfa, 0x03, 0x0a, 0x41, 0x0d, 0x67, 0x4b, 0x45, 0x08, 0x9b, 0x74, 0xbf, 0x91, 0x84, 0x9f, 0xff, + 0xc6, 0x82, 0x73, 0x99, 0x73, 0x73, 0x02, 0xc2, 0xae, 0x75, 0x53, 0xd8, 0xf5, 0xd4, 0xc0, 0xab, + 0x35, 0x47, 0xfa, 0xf5, 0x1b, 0x43, 0x39, 0xdf, 0xc2, 0x9e, 0xf2, 0x37, 0x61, 0xcc, 0x69, 0x34, + 0x48, 0x14, 0xad, 0x05, 0xae, 0x8a, 0xf2, 0xfa, 0x2c, 0x7b, 0x67, 0x25, 0xc5, 0x87, 0x07, 0xf3, + 0x73, 0x69, 0x12, 0x09, 0x18, 0xeb, 0x14, 0xd0, 0xe7, 0xa0, 0x14, 0x89, 0x7b, 0x53, 0xcc, 0xfd, + 0x0b, 0x03, 0x0e, 0x8e, 0xb3, 0x49, 0x9a, 0x66, 0x80, 0x1b, 0x25, 0xaa, 0x50, 0x24, 0xcd, 0x60, + 0x18, 0x85, 0x63, 0x0d, 0x86, 0xf1, 0x3c, 0xc0, 0x9e, 0x7a, 0x0c, 0xa4, 0x05, 0x10, 0xda, 0x33, + 0x41, 0xc3, 0x42, 0xdf, 0x02, 0xd3, 0x11, 0x0f, 0xe7, 0xb6, 0xdc, 0x74, 0x22, 0xe6, 0x31, 0x21, + 0x56, 0x21, 0x0b, 0xa2, 0x53, 0x4f, 0xc1, 0x70, 0x17, 0x36, 0x5a, 0x95, 0xad, 0xb2, 0xd8, 0x73, + 0x7c, 0x61, 0x5e, 0x4a, 0x5a, 0x14, 0x69, 0x48, 0x4f, 0xa7, 0x87, 0x9f, 0x0d, 0xbc, 0x56, 0x13, + 0x7d, 0x0e, 0x80, 0x2e, 0x1f, 0x21, 0x88, 0x18, 0xcd, 0x3f, 0x3c, 0xe9, 0xa9, 0xe2, 0x66, 0x1a, + 0x78, 0x32, 0x37, 0xc7, 0x8a, 0x22, 0x82, 0x35, 0x82, 0xf6, 0x0f, 0x0f, 0xc1, 0xa3, 0x3d, 0xce, + 0x48, 0xb4, 0x68, 0x2a, 0x4b, 0x9f, 0x4e, 0x3f, 0xae, 0xe7, 0x32, 0x2b, 0x1b, 0xaf, 0xed, 0xd4, + 0x52, 0x2c, 0xbc, 0xef, 0xa5, 0xf8, 0x03, 0x96, 0x26, 0xf6, 0xe0, 0x66, 0x7f, 0x9f, 0x3e, 0xe2, + 0xd9, 0x7f, 0x8c, 0x72, 0x90, 0xad, 0x0c, 0x61, 0xc2, 0xf3, 0x03, 0x77, 0x67, 0x60, 0xe9, 0xc2, + 0xc9, 0x8a, 0x89, 0xbf, 0x68, 0xc1, 0xe3, 0x99, 0xfd, 0x35, 0x8c, 0x3b, 0xae, 0x40, 0xb9, 0x41, + 0x0b, 0x35, 0xaf, 0xb6, 0xc4, 0xdd, 0x57, 0x02, 0x70, 0x82, 0x63, 0xd8, 0x70, 0x14, 0xfa, 0xda, + 0x70, 0xfc, 0x73, 0x0b, 0xba, 0xf6, 0xc7, 0x09, 0x1c, 0xd4, 0x55, 0xf3, 0xa0, 0xfe, 0xe8, 0x20, + 0x73, 0x99, 0x73, 0x46, 0xff, 0xc9, 0x14, 0x9c, 0xcd, 0xf1, 0xea, 0xd8, 0x83, 0x99, 0xed, 0x06, + 0x31, 0xfd, 0x05, 0xc5, 0xc7, 0x64, 0xba, 0x56, 0xf6, 0x74, 0x2e, 0x64, 0x39, 0x05, 0x67, 0xba, + 0x50, 0x70, 0x77, 0x13, 0xe8, 0x8b, 0x16, 0x9c, 0x76, 0xee, 0x46, 0x5d, 0x49, 0xc8, 0xc5, 0x9a, + 0x79, 0x31, 0x53, 0x08, 0xd2, 0x27, 0x69, 0x39, 0x4f, 0xb2, 0x98, 0x85, 0x85, 0x33, 0xdb, 0x42, + 0x58, 0xc4, 0xfd, 0xa6, 0xec, 0x7c, 0x0f, 0x8f, 0xd6, 0x2c, 0xf7, 0x1b, 0x7e, 0x83, 0x48, 0x08, + 0x56, 0x74, 0xd0, 0x17, 0xa0, 0xbc, 0x2d, 0x7d, 0xe2, 0x32, 0x6e, 0xa8, 0x64, 0x20, 0x7b, 0x7b, + 0x0a, 0x72, 0x55, 0xa6, 0x42, 0xc2, 0x09, 0x51, 0xf4, 0x3a, 0x14, 0xfd, 0xad, 0xa8, 0x57, 0x9e, + 0xc2, 0x94, 0xf5, 0x13, 0xf7, 0x1b, 0x5f, 0x5f, 0xad, 0x63, 0x5a, 0x11, 0x5d, 0x83, 0x62, 0xb8, + 0xe9, 0x0a, 0x09, 0x5e, 0xe6, 0x19, 0x8e, 0x97, 0x2a, 0x39, 0xbd, 0x62, 0x94, 0xf0, 0x52, 0x05, + 0x53, 0x12, 0xa8, 0x06, 0xc3, 0xcc, 0x15, 0x42, 0xdc, 0x07, 0x99, 0x9c, 0x6f, 0x0f, 0x97, 0x22, + 0xee, 0x5c, 0xce, 0x10, 0x30, 0x27, 0x84, 0x36, 0x60, 0xa4, 0xc1, 0x72, 0xda, 0x89, 0x48, 0x54, + 0x9f, 0xc8, 0x94, 0xd5, 0xf5, 0x48, 0xf6, 0x27, 0x44, 0x57, 0x0c, 0x03, 0x0b, 0x5a, 0x8c, 0x2a, + 0x69, 0xef, 0x6c, 0x45, 0x22, 0x07, 0x6b, 0x36, 0xd5, 0x1e, 0x39, 0x2c, 0x05, 0x55, 0x86, 0x81, + 0x05, 0x2d, 0xf4, 0x29, 0x28, 0x6c, 0x35, 0x84, 0x9b, 0x43, 0xa6, 0xd0, 0xce, 0x74, 0xfd, 0x5f, + 0x1a, 0xb9, 0x7f, 0x30, 0x5f, 0x58, 0x5d, 0xc6, 0x85, 0xad, 0x06, 0x5a, 0x87, 0xd1, 0x2d, 0xee, + 0x2c, 0x2c, 0xe4, 0x72, 0x4f, 0x66, 0xfb, 0x31, 0x77, 0xf9, 0x13, 0x73, 0x0b, 0x7f, 0x01, 0xc0, + 0x92, 0x08, 0x0b, 0xa3, 0xad, 0x9c, 0x9e, 0x45, 0x14, 0xa8, 0x85, 0xa3, 0x39, 0xaa, 0xf3, 0xfb, + 0x39, 0x71, 0x9d, 0xc6, 0x1a, 0x45, 0xba, 0xaa, 0x1d, 0x99, 0x08, 0x5b, 0x44, 0xf5, 0xc8, 0x5c, + 0xd5, 0x7d, 0x72, 0x84, 0xf3, 0x55, 0xad, 0x90, 0x70, 0x42, 0x14, 0xed, 0xc2, 0xc4, 0x5e, 0xd4, + 0xde, 0x21, 0x72, 0x4b, 0xb3, 0x20, 0x1f, 0x39, 0x57, 0xd8, 0x6d, 0x81, 0xe8, 0x85, 0x71, 0xc7, + 0x69, 0x76, 0x9d, 0x42, 0x4c, 0xff, 0x7d, 0x5b, 0x27, 0x86, 0x4d, 0xda, 0x74, 0xf8, 0xdf, 0xed, + 0x04, 0x9b, 0xfb, 0x31, 0x11, 0xc1, 0x9b, 0x32, 0x87, 0xff, 0x4d, 0x8e, 0xd2, 0x3d, 0xfc, 0x02, + 0x80, 0x25, 0x11, 0x74, 0x5b, 0x0c, 0x0f, 0x3b, 0x3d, 0xa7, 0xf3, 0x03, 0x22, 0x66, 0x66, 0xa2, + 0xd7, 0x06, 0x85, 0x9d, 0x96, 0x09, 0x29, 0x76, 0x4a, 0xb6, 0x77, 0x82, 0x38, 0xf0, 0x53, 0x27, + 0xf4, 0x4c, 0xfe, 0x29, 0x59, 0xcb, 0xc0, 0xef, 0x3e, 0x25, 0xb3, 0xb0, 0x70, 0x66, 0x5b, 0xc8, + 0x85, 0xc9, 0x76, 0x10, 0xc6, 0x77, 0x83, 0x50, 0xae, 0x2f, 0xd4, 0x43, 0xae, 0x60, 0x60, 0x8a, + 0x16, 0x59, 0x18, 0x33, 0x13, 0x82, 0x53, 0x34, 0xd1, 0x67, 0x60, 0x34, 0x6a, 0x38, 0x4d, 0x52, + 0xbd, 0x39, 0x7b, 0x2a, 0xff, 0xfa, 0xa9, 0x73, 0x94, 0x9c, 0xd5, 0xc5, 0x26, 0x47, 0xa0, 0x60, + 0x49, 0x0e, 0xad, 0xc2, 0x30, 0xcb, 0x6a, 0xc4, 0x22, 0x8d, 0xe5, 0xc4, 0x75, 0xec, 0xb2, 0x45, + 0xe5, 0x67, 0x13, 0x2b, 0xc6, 0xbc, 0x3a, 0xdd, 0x03, 0x82, 0xbd, 0x0e, 0xa2, 0xd9, 0x33, 0xf9, + 0x7b, 0x40, 0x70, 0xe5, 0x37, 0xeb, 0xbd, 0xf6, 0x80, 0x42, 0xc2, 0x09, 0x51, 0x7a, 0x32, 0xd3, + 0xd3, 0xf4, 0x6c, 0x0f, 0xd3, 0x97, 0xdc, 0xb3, 0x94, 0x9d, 0xcc, 0xf4, 0x24, 0xa5, 0x24, 0xec, + 0xdf, 0x1b, 0xed, 0xe6, 0x59, 0xd8, 0x83, 0xec, 0xbb, 0xad, 0x2e, 0x5d, 0xdd, 0x27, 0x07, 0x95, + 0x0f, 0x1d, 0x23, 0xb7, 0xfa, 0x45, 0x0b, 0xce, 0xb6, 0x33, 0x3f, 0x44, 0x30, 0x00, 0x83, 0x89, + 0x99, 0xf8, 0xa7, 0xab, 0xa8, 0x74, 0xd9, 0x70, 0x9c, 0xd3, 0x52, 0xfa, 0x45, 0x50, 0x7c, 0xdf, + 0x2f, 0x82, 0x35, 0x28, 0x31, 0x26, 0xb3, 0x4f, 0x8e, 0xd7, 0xf4, 0xc3, 0x88, 0xb1, 0x12, 0xcb, + 0xa2, 0x22, 0x56, 0x24, 0xd0, 0x0f, 0x5a, 0x70, 0x3e, 0xdd, 0x75, 0x4c, 0x18, 0x58, 0x84, 0xb2, + 0xe3, 0x6f, 0xc1, 0x55, 0xf1, 0xfd, 0xe7, 0x6b, 0xbd, 0x90, 0x0f, 0xfb, 0x21, 0xe0, 0xde, 0x8d, + 0xa1, 0x4a, 0xc6, 0x63, 0x74, 0xc4, 0x14, 0xc0, 0x0f, 0xf0, 0x20, 0x7d, 0x11, 0xc6, 0x5b, 0x41, + 0xc7, 0x8f, 0x85, 0xa5, 0x8c, 0xd0, 0xda, 0x33, 0x6d, 0xf5, 0x9a, 0x56, 0x8e, 0x0d, 0xac, 0xd4, + 0x33, 0xb6, 0xf4, 0xc0, 0xcf, 0xd8, 0xb7, 0x61, 0xdc, 0xd7, 0x4c, 0x3b, 0x05, 0x3f, 0x70, 0x29, + 0x3f, 0x6a, 0xa4, 0x6e, 0x08, 0xca, 0x7b, 0xa9, 0x97, 0x60, 0x83, 0xda, 0xc9, 0xbe, 0x8d, 0x7e, + 0xc6, 0xca, 0x60, 0xea, 0xf9, 0x6b, 0xf9, 0x35, 0xf3, 0xb5, 0x7c, 0x29, 0xfd, 0x5a, 0xee, 0x12, + 0xbe, 0x1a, 0x0f, 0xe5, 0xc1, 0x53, 0x57, 0x0c, 0x1a, 0x71, 0xce, 0x6e, 0xc2, 0xc5, 0x7e, 0xd7, + 0x12, 0x33, 0x99, 0x72, 0x95, 0xaa, 0x2d, 0x31, 0x99, 0x72, 0xab, 0x15, 0xcc, 0x20, 0x83, 0x86, + 0x24, 0xb1, 0xff, 0xbb, 0x05, 0xc5, 0x5a, 0xe0, 0x9e, 0x80, 0x30, 0xf9, 0xd3, 0x86, 0x30, 0xf9, + 0xd1, 0xec, 0x0b, 0xd1, 0xcd, 0x15, 0x1d, 0xaf, 0xa4, 0x44, 0xc7, 0xe7, 0xf3, 0x08, 0xf4, 0x16, + 0x14, 0xff, 0x64, 0x11, 0xc6, 0x6a, 0x81, 0xab, 0xec, 0x95, 0x7f, 0xe3, 0x41, 0xec, 0x95, 0x73, + 0x43, 0xbb, 0x6b, 0x94, 0x99, 0xa5, 0x95, 0x74, 0xd7, 0xfb, 0x2b, 0x66, 0xb6, 0x7c, 0x87, 0x78, + 0xdb, 0x3b, 0x31, 0x71, 0xd3, 0x9f, 0x73, 0x72, 0x66, 0xcb, 0xff, 0xcd, 0x82, 0xa9, 0x54, 0xeb, + 0xa8, 0x09, 0x13, 0x4d, 0x5d, 0x30, 0x29, 0xd6, 0xe9, 0x03, 0xc9, 0x34, 0x85, 0xd9, 0xa7, 0x56, + 0x84, 0x4d, 0xe2, 0x68, 0x01, 0x40, 0x69, 0xea, 0xa4, 0x04, 0x8c, 0x71, 0xfd, 0x4a, 0x95, 0x17, + 0x61, 0x0d, 0x03, 0xbd, 0x04, 0x63, 0x71, 0xd0, 0x0e, 0x9a, 0xc1, 0xf6, 0xfe, 0x75, 0x22, 0x83, + 0xe0, 0x28, 0x63, 0xae, 0x8d, 0x04, 0x84, 0x75, 0x3c, 0xfb, 0xa7, 0x8b, 0xfc, 0x43, 0xfd, 0xd8, + 0xfb, 0x70, 0x4d, 0x7e, 0xb0, 0xd7, 0xe4, 0xd7, 0x2c, 0x98, 0xa6, 0xad, 0x33, 0x73, 0x11, 0x79, + 0xd9, 0xaa, 0xf0, 0xb3, 0x56, 0x8f, 0xf0, 0xb3, 0x97, 0xe8, 0xd9, 0xe5, 0x06, 0x9d, 0x58, 0x48, + 0xd0, 0xb4, 0xc3, 0x89, 0x96, 0x62, 0x01, 0x15, 0x78, 0x24, 0x0c, 0x85, 0xb7, 0x94, 0x8e, 0x47, + 0xc2, 0x10, 0x0b, 0xa8, 0x8c, 0x4e, 0x3b, 0x94, 0x1d, 0x9d, 0x96, 0x87, 0xf4, 0x13, 0x86, 0x05, + 0x82, 0xed, 0xd1, 0x42, 0xfa, 0x49, 0x8b, 0x83, 0x04, 0xc7, 0xfe, 0x4a, 0x11, 0xc6, 0x6b, 0x81, + 0x9b, 0xe8, 0xca, 0x5e, 0x34, 0x74, 0x65, 0x17, 0x53, 0xba, 0xb2, 0x69, 0x1d, 0xf7, 0x43, 0xcd, + 0xd8, 0xd7, 0x4b, 0x33, 0xf6, 0xcf, 0x2c, 0x36, 0x6b, 0x95, 0xf5, 0xba, 0xc8, 0xf0, 0xff, 0x1c, + 0x8c, 0xb1, 0x03, 0x89, 0xb9, 0xe7, 0x49, 0x05, 0x12, 0x4b, 0x9e, 0xb3, 0x9e, 0x14, 0x63, 0x1d, + 0x07, 0x5d, 0x86, 0x52, 0x44, 0x9c, 0xb0, 0xb1, 0xa3, 0xce, 0x38, 0xa1, 0xed, 0xe1, 0x65, 0x58, + 0x41, 0xd1, 0x9b, 0x49, 0x34, 0xb9, 0x62, 0x7e, 0xb0, 0x61, 0xbd, 0x3f, 0x7c, 0x8b, 0xe4, 0x87, + 0x90, 0xb3, 0xef, 0x00, 0xea, 0xc6, 0x1f, 0x20, 0x8c, 0xd2, 0xbc, 0x19, 0x46, 0xa9, 0xdc, 0x15, + 0x42, 0xe9, 0x2f, 0x2c, 0x98, 0xac, 0x05, 0x2e, 0xdd, 0xba, 0xdf, 0x48, 0xfb, 0x54, 0x0f, 0xa5, + 0x39, 0xd2, 0x23, 0x94, 0xe6, 0x13, 0x30, 0x5c, 0x0b, 0xdc, 0x6a, 0xad, 0x97, 0x9b, 0xac, 0xfd, + 0x77, 0x2d, 0x18, 0xad, 0x05, 0xee, 0x09, 0x08, 0xe7, 0x5f, 0x33, 0x85, 0xf3, 0x8f, 0xe4, 0xac, + 0x9b, 0x1c, 0x79, 0xfc, 0x2f, 0x16, 0x61, 0x82, 0xf6, 0x33, 0xd8, 0x96, 0x53, 0x69, 0x0c, 0x9b, + 0x35, 0xc0, 0xb0, 0x51, 0x5e, 0x38, 0x68, 0x36, 0x83, 0xbb, 0xe9, 0x69, 0x5d, 0x65, 0xa5, 0x58, + 0x40, 0xd1, 0x33, 0x50, 0x6a, 0x87, 0x64, 0xcf, 0x0b, 0x04, 0x93, 0xa9, 0xa9, 0x3a, 0x6a, 0xa2, + 0x1c, 0x2b, 0x0c, 0xfa, 0x38, 0x8b, 0x3c, 0xbf, 0x41, 0xea, 0xa4, 0x11, 0xf8, 0x2e, 0x97, 0x5f, + 0x17, 0x45, 0x8a, 0x0b, 0xad, 0x1c, 0x1b, 0x58, 0xe8, 0x0e, 0x94, 0xd9, 0x7f, 0x76, 0xec, 0x1c, + 0x3d, 0x41, 0xa0, 0xc8, 0x2b, 0x25, 0x08, 0xe0, 0x84, 0x16, 0x7a, 0x1e, 0x20, 0x96, 0xc1, 0x96, + 0x23, 0x11, 0x32, 0x47, 0x31, 0xe4, 0x2a, 0x0c, 0x73, 0x84, 0x35, 0x2c, 0xf4, 0x34, 0x94, 0x63, + 0xc7, 0x6b, 0xde, 0xf0, 0x7c, 0x12, 0x31, 0xb9, 0x74, 0x51, 0xa6, 0x77, 0x12, 0x85, 0x38, 0x81, + 0x53, 0x86, 0x88, 0xf9, 0x93, 0xf3, 0xf4, 0xa2, 0x25, 0x86, 0xcd, 0x18, 0xa2, 0x1b, 0xaa, 0x14, + 0x6b, 0x18, 0xf6, 0x2b, 0x70, 0xa6, 0x16, 0xb8, 0xb5, 0x20, 0x8c, 0x57, 0x83, 0xf0, 0xae, 0x13, + 0xba, 0x72, 0xfe, 0xe6, 0x65, 0x56, 0x08, 0x7a, 0x40, 0x0d, 0xf3, 0xed, 0x6b, 0xe4, 0x26, 0x7a, + 0x81, 0xb1, 0x44, 0x47, 0xf4, 0x11, 0x69, 0xb0, 0xcb, 0x59, 0xc5, 0xff, 0xbf, 0xea, 0xc4, 0x04, + 0xdd, 0x64, 0xd9, 0x47, 0x93, 0x7b, 0x4a, 0x54, 0x7f, 0x4a, 0xcb, 0x3e, 0x9a, 0x00, 0x33, 0x2f, + 0x36, 0xb3, 0xbe, 0xfd, 0x73, 0x43, 0xec, 0xc8, 0x4a, 0x05, 0xa5, 0x47, 0x9f, 0x87, 0xc9, 0x88, + 0xdc, 0xf0, 0xfc, 0xce, 0x3d, 0xf9, 0x52, 0xef, 0xe1, 0xe5, 0x53, 0x5f, 0xd1, 0x31, 0xb9, 0xbc, + 0xcf, 0x2c, 0xc3, 0x29, 0x6a, 0xa8, 0x05, 0x93, 0x77, 0x3d, 0xdf, 0x0d, 0xee, 0x46, 0x92, 0x7e, + 0x29, 0x5f, 0xec, 0x77, 0x87, 0x63, 0xa6, 0xfa, 0x68, 0x34, 0x77, 0xc7, 0x20, 0x86, 0x53, 0xc4, + 0xe9, 0xb2, 0x08, 0x3b, 0xfe, 0x62, 0x74, 0x2b, 0x22, 0xa1, 0xc8, 0x23, 0xcb, 0x96, 0x05, 0x96, + 0x85, 0x38, 0x81, 0xd3, 0x65, 0xc1, 0xfe, 0x5c, 0x0d, 0x83, 0x0e, 0x0f, 0x54, 0x2e, 0x96, 0x05, + 0x56, 0xa5, 0x58, 0xc3, 0xa0, 0xdb, 0x86, 0xfd, 0x5b, 0x0f, 0x7c, 0x1c, 0x04, 0xb1, 0xdc, 0x68, + 0x2c, 0x73, 0xa1, 0x56, 0x8e, 0x0d, 0x2c, 0xb4, 0x0a, 0x28, 0xea, 0xb4, 0xdb, 0x4d, 0x66, 0x3d, + 0xe0, 0x34, 0x19, 0x29, 0xae, 0xb9, 0x2d, 0xf2, 0x30, 0x8c, 0xf5, 0x2e, 0x28, 0xce, 0xa8, 0x41, + 0x4f, 0xd0, 0x2d, 0xd1, 0xd5, 0x61, 0xd6, 0x55, 0xae, 0x22, 0xa8, 0xf3, 0x7e, 0x4a, 0x18, 0x5a, + 0x81, 0xd1, 0x68, 0x3f, 0x6a, 0xc4, 0x22, 0x9e, 0x54, 0x4e, 0x9a, 0x90, 0x3a, 0x43, 0xd1, 0xb2, + 0x54, 0xf1, 0x2a, 0x58, 0xd6, 0xb5, 0xbf, 0x83, 0x5d, 0xd0, 0x2c, 0xeb, 0x68, 0xdc, 0x09, 0x09, + 0x6a, 0xc1, 0x44, 0x9b, 0xad, 0x30, 0x11, 0x79, 0x5b, 0x2c, 0x93, 0x17, 0x07, 0x7c, 0x69, 0xdf, + 0xa5, 0xe7, 0x9a, 0x92, 0x84, 0xb1, 0x27, 0x4c, 0x4d, 0x27, 0x87, 0x4d, 0xea, 0xf6, 0xd7, 0xce, + 0xb2, 0x23, 0xbe, 0xce, 0x9f, 0xcf, 0xa3, 0xc2, 0xdc, 0x59, 0xbc, 0x15, 0xe6, 0xf2, 0xe5, 0x38, + 0xc9, 0x17, 0x09, 0x93, 0x69, 0x2c, 0xeb, 0xa2, 0xcf, 0xc1, 0x24, 0x65, 0xbd, 0xb5, 0xcc, 0x03, + 0xa7, 0xf3, 0x5d, 0xc7, 0x93, 0x84, 0x03, 0x5a, 0x54, 0x7e, 0xbd, 0x32, 0x4e, 0x11, 0x43, 0x6f, + 0x32, 0xc5, 0xbc, 0x99, 0xd4, 0xa0, 0x0f, 0x69, 0x5d, 0x07, 0x2f, 0xc9, 0x6a, 0x44, 0xf2, 0x12, + 0x26, 0xd8, 0x0f, 0x37, 0x61, 0x02, 0xba, 0x01, 0x13, 0x22, 0xf5, 0xa6, 0x10, 0x3f, 0x16, 0x0d, + 0xf1, 0xd2, 0x04, 0xd6, 0x81, 0x87, 0xe9, 0x02, 0x6c, 0x56, 0x46, 0xdb, 0x70, 0x5e, 0xcb, 0xda, + 0x71, 0x35, 0x74, 0x98, 0x8e, 0xd8, 0x63, 0x27, 0x91, 0x76, 0xf9, 0x3c, 0x7e, 0xff, 0x60, 0xfe, + 0xfc, 0x46, 0x2f, 0x44, 0xdc, 0x9b, 0x0e, 0xba, 0x09, 0x67, 0xb8, 0x57, 0x65, 0x85, 0x38, 0x6e, + 0xd3, 0xf3, 0xd5, 0xed, 0xc6, 0x77, 0xcb, 0xb9, 0xfb, 0x07, 0xf3, 0x67, 0x16, 0xb3, 0x10, 0x70, + 0x76, 0x3d, 0xf4, 0x1a, 0x94, 0x5d, 0x3f, 0x12, 0x63, 0x30, 0x62, 0x24, 0x46, 0x29, 0x57, 0xd6, + 0xeb, 0xea, 0xfb, 0x93, 0x3f, 0x38, 0xa9, 0x80, 0xb6, 0xb9, 0x08, 0x52, 0xbd, 0xf8, 0x47, 0xbb, + 0x22, 0x8b, 0xa4, 0x65, 0x47, 0x86, 0x5f, 0x15, 0x97, 0xbd, 0x2b, 0x6b, 0x63, 0xc3, 0xe5, 0xca, + 0x20, 0x8c, 0xde, 0x00, 0x44, 0x59, 0x62, 0xaf, 0x41, 0x16, 0x1b, 0x2c, 0xac, 0x3b, 0x93, 0xd8, + 0x96, 0x0c, 0xef, 0x14, 0x54, 0xef, 0xc2, 0xc0, 0x19, 0xb5, 0xd0, 0x35, 0x7a, 0x1b, 0xe8, 0xa5, + 0xc2, 0x6a, 0x5a, 0x65, 0x9d, 0xaa, 0x90, 0x76, 0x48, 0x1a, 0x4e, 0x4c, 0x5c, 0x93, 0x22, 0x4e, + 0xd5, 0x43, 0x2e, 0x3c, 0xe6, 0x74, 0xe2, 0x80, 0x49, 0x77, 0x4d, 0xd4, 0x8d, 0x60, 0x97, 0xf8, + 0x4c, 0xb1, 0x52, 0x5a, 0xba, 0x78, 0xff, 0x60, 0xfe, 0xb1, 0xc5, 0x1e, 0x78, 0xb8, 0x27, 0x15, + 0xca, 0xf6, 0xa8, 0x9c, 0x91, 0x60, 0x06, 0x4c, 0xc9, 0xc8, 0x1b, 0xf9, 0x12, 0x8c, 0xed, 0x04, + 0x51, 0xbc, 0x4e, 0xe2, 0xbb, 0x41, 0xb8, 0x2b, 0xc2, 0xde, 0x25, 0xa1, 0x52, 0x13, 0x10, 0xd6, + 0xf1, 0xe8, 0xbb, 0x86, 0xa9, 0xfd, 0xab, 0x15, 0xa6, 0x71, 0x2d, 0x25, 0x67, 0xcc, 0x35, 0x5e, + 0x8c, 0x25, 0x5c, 0xa2, 0x56, 0x6b, 0xcb, 0x4c, 0x7b, 0x9a, 0x42, 0xad, 0xd6, 0x96, 0xb1, 0x84, + 0xd3, 0xe5, 0x1a, 0xed, 0x38, 0x21, 0xa9, 0x85, 0x41, 0x83, 0x44, 0x5a, 0x80, 0xde, 0x47, 0x79, + 0x50, 0x3f, 0xba, 0x5c, 0xeb, 0x59, 0x08, 0x38, 0xbb, 0x1e, 0x22, 0xdd, 0x19, 0x6b, 0x26, 0xf3, + 0xc5, 0xde, 0xdd, 0xac, 0xc0, 0x80, 0x49, 0x6b, 0x7c, 0x98, 0x56, 0xb9, 0x72, 0x78, 0x18, 0xbf, + 0x68, 0x76, 0x8a, 0xad, 0xed, 0xc1, 0x63, 0x00, 0x2a, 0x45, 0x42, 0x35, 0x45, 0x09, 0x77, 0xd1, + 0x36, 0x62, 0xe2, 0x4c, 0xf7, 0x4d, 0x22, 0x7a, 0x05, 0xca, 0x51, 0x67, 0xd3, 0x0d, 0x5a, 0x8e, + 0xe7, 0x33, 0xed, 0xa9, 0xc6, 0x60, 0xd7, 0x25, 0x00, 0x27, 0x38, 0x68, 0x15, 0x4a, 0x8e, 0xd4, + 0x12, 0xa0, 0xfc, 0x00, 0x18, 0x4a, 0x37, 0xc0, 0x7d, 0xc2, 0xa5, 0x5e, 0x40, 0xd5, 0x45, 0xaf, + 0xc2, 0x84, 0xf0, 0x0a, 0x14, 0x59, 0xd5, 0x4e, 0x99, 0x9e, 0x1b, 0x75, 0x1d, 0x88, 0x4d, 0x5c, + 0x74, 0x0b, 0xc6, 0xe2, 0xa0, 0xc9, 0xdc, 0x0f, 0x28, 0x87, 0x74, 0x36, 0x3f, 0x1c, 0xd3, 0x86, + 0x42, 0xd3, 0x05, 0x74, 0xaa, 0x2a, 0xd6, 0xe9, 0xa0, 0x0d, 0xbe, 0xde, 0x59, 0xa0, 0x5a, 0x12, + 0xcd, 0x3e, 0x92, 0x7f, 0x27, 0xa9, 0x78, 0xb6, 0xe6, 0x76, 0x10, 0x35, 0xb1, 0x4e, 0x06, 0x5d, + 0x85, 0x99, 0x76, 0xe8, 0x05, 0x6c, 0x4d, 0x28, 0x05, 0xd1, 0xac, 0x99, 0x5e, 0xa3, 0x96, 0x46, + 0xc0, 0xdd, 0x75, 0x98, 0x53, 0xa7, 0x28, 0x9c, 0x3d, 0xc7, 0xb3, 0xa8, 0xf2, 0xf7, 0x0a, 0x2f, + 0xc3, 0x0a, 0x8a, 0xd6, 0xd8, 0x49, 0xcc, 0x9f, 0xda, 0xb3, 0x73, 0xf9, 0x31, 0x37, 0xf4, 0x27, + 0x39, 0xe7, 0xfb, 0xd4, 0x5f, 0x9c, 0x50, 0x40, 0xae, 0x96, 0xa1, 0x8b, 0x32, 0xdb, 0xd1, 0xec, + 0x63, 0x3d, 0x6c, 0xaf, 0x52, 0x9c, 0x79, 0xc2, 0x10, 0x18, 0xc5, 0x11, 0x4e, 0xd1, 0x44, 0xdf, + 0x02, 0xd3, 0x22, 0x5a, 0x54, 0x32, 0x4c, 0xe7, 0x13, 0xa3, 0x4e, 0x9c, 0x82, 0xe1, 0x2e, 0x6c, + 0x1e, 0xc0, 0xdb, 0xd9, 0x6c, 0x12, 0x71, 0xf4, 0xdd, 0xf0, 0xfc, 0xdd, 0x68, 0xf6, 0x02, 0x3b, + 0x1f, 0x44, 0x00, 0xef, 0x34, 0x14, 0x67, 0xd4, 0x40, 0x1b, 0x30, 0xdd, 0x0e, 0x09, 0x69, 0x31, + 0x1e, 0x59, 0xdc, 0x67, 0xf3, 0xdc, 0xa7, 0x99, 0xf6, 0xa4, 0x96, 0x82, 0x1d, 0x66, 0x94, 0xe1, + 0x2e, 0x0a, 0xe8, 0x2e, 0x94, 0x82, 0x3d, 0x12, 0xee, 0x10, 0xc7, 0x9d, 0xbd, 0xd8, 0xc3, 0xc8, + 0x58, 0x5c, 0x6e, 0x37, 0x05, 0x6e, 0x4a, 0xa9, 0x2c, 0x8b, 0xfb, 0x2b, 0x95, 0x65, 0x63, 0xe8, + 0x87, 0x2c, 0x38, 0x27, 0xe5, 0xd0, 0xf5, 0x36, 0x1d, 0xf5, 0xe5, 0xc0, 0x8f, 0xe2, 0x90, 0x7b, + 0xe1, 0x3e, 0x9e, 0xef, 0x98, 0xba, 0x91, 0x53, 0x49, 0x49, 0xfb, 0xce, 0xe5, 0x61, 0x44, 0x38, + 0xbf, 0xc5, 0xb9, 0x6f, 0x86, 0x99, 0xae, 0x9b, 0xfb, 0x28, 0x39, 0x05, 0xe6, 0x76, 0x61, 0xc2, + 0x18, 0x9d, 0x87, 0xaa, 0x4f, 0xfc, 0xd7, 0xa3, 0x50, 0x56, 0xba, 0x26, 0x74, 0xc5, 0x54, 0x21, + 0x9e, 0x4b, 0xab, 0x10, 0x4b, 0xf4, 0x35, 0xab, 0x6b, 0x0d, 0x37, 0x0c, 0xfb, 0xd3, 0x42, 0x7e, + 0x36, 0x3e, 0xfd, 0x3d, 0xda, 0xd7, 0x97, 0x55, 0x13, 0x1d, 0x16, 0x07, 0xd6, 0x45, 0x0e, 0xf5, + 0x94, 0x46, 0x5e, 0x85, 0x19, 0x3f, 0x60, 0xec, 0x22, 0x71, 0x25, 0x2f, 0xc0, 0xae, 0xfc, 0xb2, + 0x1e, 0x44, 0x20, 0x85, 0x80, 0xbb, 0xeb, 0xd0, 0x06, 0xf9, 0x9d, 0x9d, 0x16, 0x7f, 0xf2, 0x2b, + 0x1d, 0x0b, 0x28, 0x7a, 0x02, 0x86, 0xdb, 0x81, 0x5b, 0xad, 0xa5, 0x33, 0xd4, 0x33, 0x79, 0x16, + 0xe6, 0x30, 0xb4, 0x08, 0x23, 0xec, 0x47, 0x34, 0x3b, 0x9e, 0xef, 0x2d, 0xce, 0x6a, 0x68, 0x19, + 0x1b, 0x58, 0x05, 0x2c, 0x2a, 0x32, 0x31, 0x0c, 0xe5, 0xaf, 0x99, 0x18, 0x66, 0xf4, 0x01, 0xc5, + 0x30, 0x92, 0x00, 0x4e, 0x68, 0xa1, 0x7b, 0x70, 0xc6, 0x78, 0xd3, 0xf0, 0x25, 0x42, 0x22, 0xe1, + 0xb0, 0xfa, 0x44, 0xcf, 0xc7, 0x8c, 0xd0, 0x5d, 0x9e, 0x17, 0x9d, 0x3e, 0x53, 0xcd, 0xa2, 0x84, + 0xb3, 0x1b, 0x40, 0x4d, 0x98, 0x69, 0x74, 0xb5, 0x5a, 0x1a, 0xbc, 0x55, 0x35, 0xa1, 0xdd, 0x2d, + 0x76, 0x13, 0x46, 0xaf, 0x42, 0xe9, 0xdd, 0x20, 0x62, 0xc7, 0xac, 0x60, 0x6f, 0xa5, 0xb7, 0x63, + 0xe9, 0xcd, 0x9b, 0x75, 0x56, 0x7e, 0x78, 0x30, 0x3f, 0x56, 0x0b, 0x5c, 0xf9, 0x17, 0xab, 0x0a, + 0xe8, 0xfb, 0x2c, 0x98, 0xeb, 0x7e, 0x34, 0xa9, 0x4e, 0x4f, 0x0c, 0xde, 0x69, 0x5b, 0x34, 0x3a, + 0xb7, 0x92, 0x4b, 0x0e, 0xf7, 0x68, 0xca, 0xfe, 0x15, 0xae, 0x67, 0x14, 0xda, 0x08, 0x12, 0x75, + 0x9a, 0x27, 0x91, 0xe1, 0x6e, 0xc5, 0x50, 0x94, 0x3c, 0xb0, 0x2e, 0xfb, 0xd7, 0x2d, 0xa6, 0xcb, + 0xde, 0x20, 0xad, 0x76, 0xd3, 0x89, 0x4f, 0xc2, 0x59, 0xee, 0x4d, 0x28, 0xc5, 0xa2, 0xb5, 0x5e, + 0x49, 0xf9, 0xb4, 0x4e, 0x31, 0x7d, 0xbe, 0x62, 0x36, 0x65, 0x29, 0x56, 0x64, 0xec, 0x7f, 0xcc, + 0x67, 0x40, 0x42, 0x4e, 0x40, 0x1e, 0x5d, 0x31, 0xe5, 0xd1, 0xf3, 0x7d, 0xbe, 0x20, 0x47, 0x2e, + 0xfd, 0x8f, 0xcc, 0x7e, 0x33, 0x21, 0xcb, 0x07, 0xdd, 0x88, 0xc2, 0xfe, 0x11, 0x0b, 0x4e, 0x67, + 0x59, 0x1d, 0xd2, 0x07, 0x02, 0x17, 0xf1, 0x28, 0xa3, 0x12, 0x35, 0x82, 0xb7, 0x45, 0x39, 0x56, + 0x18, 0x03, 0xe7, 0xbb, 0x39, 0x5a, 0xfc, 0xc7, 0x9b, 0x30, 0x51, 0x0b, 0x89, 0x76, 0xa1, 0xbd, + 0xce, 0xbd, 0x5f, 0x79, 0x7f, 0x9e, 0x39, 0xb2, 0xe7, 0xab, 0xfd, 0xb3, 0x05, 0x38, 0xcd, 0xb5, + 0xc2, 0x8b, 0x7b, 0x81, 0xe7, 0xd6, 0x02, 0x57, 0xe4, 0x2a, 0x7a, 0x0b, 0xc6, 0xdb, 0x9a, 0x5c, + 0xae, 0x57, 0x04, 0x3a, 0x5d, 0x7e, 0x97, 0x48, 0x12, 0xf4, 0x52, 0x6c, 0xd0, 0x42, 0x2e, 0x8c, + 0x93, 0x3d, 0xaf, 0xa1, 0x54, 0x8b, 0x85, 0x23, 0x5f, 0x2e, 0xaa, 0x95, 0x15, 0x8d, 0x0e, 0x36, + 0xa8, 0x3e, 0x84, 0xf4, 0x95, 0xf6, 0x8f, 0x5a, 0xf0, 0x48, 0x4e, 0xbc, 0x3a, 0xda, 0xdc, 0x5d, + 0xa6, 0x7f, 0x17, 0x99, 0xf0, 0x54, 0x73, 0x5c, 0x2b, 0x8f, 0x05, 0x14, 0x7d, 0x06, 0x80, 0x6b, + 0xd5, 0xe9, 0x0b, 0xb5, 0x5f, 0x60, 0x2f, 0x23, 0x26, 0x91, 0x16, 0x5e, 0x46, 0xd6, 0xc7, 0x1a, + 0x2d, 0xfb, 0xa7, 0x8a, 0x30, 0xcc, 0x73, 0xf8, 0xae, 0xc2, 0xe8, 0x0e, 0x8f, 0xe0, 0x3e, 0x48, + 0xb0, 0xf8, 0x44, 0x76, 0xc0, 0x0b, 0xb0, 0xac, 0x8c, 0xd6, 0xe0, 0x14, 0x8f, 0x80, 0xdf, 0xac, + 0x90, 0xa6, 0xb3, 0x2f, 0x05, 0x5d, 0x3c, 0x7b, 0x9c, 0x12, 0xf8, 0x55, 0xbb, 0x51, 0x70, 0x56, + 0x3d, 0xf4, 0x3a, 0x4c, 0xd2, 0x87, 0x47, 0xd0, 0x89, 0x25, 0x25, 0x1e, 0xfb, 0x5e, 0xbd, 0x74, + 0x36, 0x0c, 0x28, 0x4e, 0x61, 0xd3, 0xb7, 0x6f, 0xbb, 0x4b, 0xa4, 0x37, 0x9c, 0xbc, 0x7d, 0x4d, + 0x31, 0x9e, 0x89, 0xcb, 0xcc, 0x0d, 0x3b, 0xcc, 0xb8, 0x72, 0x63, 0x27, 0x24, 0xd1, 0x4e, 0xd0, + 0x74, 0x19, 0xa3, 0x35, 0xac, 0x99, 0x1b, 0xa6, 0xe0, 0xb8, 0xab, 0x06, 0xa5, 0xb2, 0xe5, 0x78, + 0xcd, 0x4e, 0x48, 0x12, 0x2a, 0x23, 0x26, 0x95, 0xd5, 0x14, 0x1c, 0x77, 0xd5, 0xa0, 0xeb, 0xe8, + 0x4c, 0x2d, 0x0c, 0xe8, 0xe1, 0x25, 0x63, 0x70, 0x28, 0x1b, 0xd2, 0x51, 0xe9, 0x2e, 0xd8, 0x23, + 0x5c, 0x95, 0xb0, 0xb2, 0xe3, 0x14, 0x0c, 0x05, 0x72, 0x5d, 0x38, 0x0a, 0x4a, 0x2a, 0xe8, 0x39, + 0x18, 0x13, 0x71, 0xcd, 0x99, 0xa9, 0x23, 0x9f, 0x3a, 0xa6, 0xf0, 0xae, 0x24, 0xc5, 0x58, 0xc7, + 0xb1, 0xbf, 0xbf, 0x00, 0xa7, 0x32, 0x6c, 0xd5, 0xf9, 0x51, 0xb5, 0xed, 0x45, 0xb1, 0xca, 0x90, + 0xa5, 0x1d, 0x55, 0xbc, 0x1c, 0x2b, 0x0c, 0xba, 0x1f, 0xf8, 0x61, 0x98, 0x3e, 0x00, 0x85, 0x2d, + 0xa8, 0x80, 0x1e, 0x31, 0xd7, 0xd4, 0x45, 0x18, 0xea, 0x44, 0x44, 0x06, 0x9a, 0x53, 0xe7, 0x37, + 0xd3, 0xb8, 0x30, 0x08, 0x65, 0x8f, 0xb7, 0x95, 0xf2, 0x42, 0x63, 0x8f, 0xb9, 0xfa, 0x82, 0xc3, + 0x68, 0xe7, 0x62, 0xe2, 0x3b, 0x7e, 0x2c, 0x98, 0xe8, 0x24, 0x62, 0x12, 0x2b, 0xc5, 0x02, 0x6a, + 0x7f, 0xb9, 0x08, 0xe7, 0x72, 0xbd, 0x57, 0x68, 0xd7, 0x5b, 0x81, 0xef, 0xc5, 0x81, 0xb2, 0x24, + 0xe0, 0x51, 0x92, 0x48, 0x7b, 0x67, 0x4d, 0x94, 0x63, 0x85, 0x81, 0x2e, 0x99, 0x79, 0xe8, 0x93, + 0xaf, 0x5c, 0xaa, 0x18, 0xa9, 0xe8, 0x07, 0xcd, 0xc3, 0xf8, 0x04, 0x0c, 0xb5, 0x83, 0xa0, 0x99, + 0x3e, 0xb4, 0x68, 0x77, 0x83, 0xa0, 0x89, 0x19, 0x10, 0x7d, 0x4c, 0x8c, 0x57, 0x4a, 0x75, 0x8e, + 0x1d, 0x37, 0x88, 0xb4, 0x41, 0x7b, 0x0a, 0x46, 0x77, 0xc9, 0x7e, 0xe8, 0xf9, 0xdb, 0x69, 0x93, + 0x8a, 0xeb, 0xbc, 0x18, 0x4b, 0xb8, 0x99, 0xf6, 0x65, 0xf4, 0xb8, 0x13, 0x28, 0x96, 0xfa, 0x5e, + 0x81, 0x3f, 0x50, 0x84, 0x29, 0xbc, 0x54, 0xf9, 0x70, 0x22, 0x6e, 0x75, 0x4f, 0xc4, 0x71, 0x27, + 0x50, 0xec, 0x3f, 0x1b, 0xbf, 0x68, 0xc1, 0x14, 0x8b, 0xae, 0x2e, 0xc2, 0xeb, 0x78, 0x81, 0x7f, + 0x02, 0x2c, 0xde, 0x13, 0x30, 0x1c, 0xd2, 0x46, 0xd3, 0x49, 0xc2, 0x58, 0x4f, 0x30, 0x87, 0xa1, + 0xc7, 0x60, 0x88, 0x75, 0x81, 0x4e, 0xde, 0x38, 0xcf, 0xaf, 0x52, 0x71, 0x62, 0x07, 0xb3, 0x52, + 0x16, 0x33, 0x02, 0x93, 0x76, 0xd3, 0xe3, 0x9d, 0x4e, 0x54, 0x82, 0x1f, 0x8c, 0x98, 0x11, 0x99, + 0x5d, 0x7b, 0x7f, 0x31, 0x23, 0xb2, 0x49, 0xf6, 0x7e, 0x3e, 0xfd, 0x71, 0x01, 0x2e, 0x64, 0xd6, + 0x1b, 0x38, 0x66, 0x44, 0xef, 0xda, 0xc7, 0x63, 0x19, 0x97, 0x6d, 0xb0, 0x56, 0x3c, 0x41, 0x83, + 0xb5, 0xa1, 0x41, 0x39, 0xcc, 0xe1, 0x01, 0x42, 0x39, 0x64, 0x0e, 0xd9, 0x07, 0x24, 0x94, 0x43, + 0x66, 0xdf, 0x72, 0x9e, 0x7f, 0x7f, 0x59, 0xc8, 0xf9, 0x16, 0xf6, 0x10, 0xbc, 0x4c, 0xcf, 0x19, + 0x06, 0x8c, 0x04, 0xc7, 0x3c, 0xce, 0xcf, 0x18, 0x5e, 0x86, 0x15, 0x14, 0x2d, 0xc2, 0x54, 0xcb, + 0xf3, 0xe9, 0xe1, 0xb3, 0x6f, 0x32, 0x7e, 0x2a, 0xd2, 0xce, 0x9a, 0x09, 0xc6, 0x69, 0x7c, 0xe4, + 0x69, 0x61, 0x1e, 0x0a, 0xf9, 0x69, 0x77, 0x73, 0x7b, 0xbb, 0x60, 0xaa, 0x4b, 0xd5, 0x28, 0x66, + 0x84, 0x7c, 0x58, 0xd3, 0xde, 0xff, 0xc5, 0xc1, 0xdf, 0xff, 0xe3, 0xd9, 0x6f, 0xff, 0xb9, 0x57, + 0x61, 0xe2, 0x81, 0x05, 0xbe, 0xf6, 0xd7, 0x8a, 0xf0, 0x68, 0x8f, 0x6d, 0xcf, 0xcf, 0x7a, 0x63, + 0x0e, 0xb4, 0xb3, 0xbe, 0x6b, 0x1e, 0x6a, 0x70, 0x7a, 0xab, 0xd3, 0x6c, 0xee, 0x33, 0x9b, 0x70, + 0xe2, 0x4a, 0x0c, 0xc1, 0x53, 0x3e, 0x26, 0x33, 0xda, 0xac, 0x66, 0xe0, 0xe0, 0xcc, 0x9a, 0x94, + 0xa1, 0xa7, 0x37, 0xc9, 0xbe, 0x22, 0x95, 0x62, 0xe8, 0xb1, 0x0e, 0xc4, 0x26, 0x2e, 0xba, 0x0a, + 0x33, 0xce, 0x9e, 0xe3, 0xf1, 0x60, 0x99, 0x92, 0x00, 0xe7, 0xe8, 0x95, 0x9c, 0x6e, 0x31, 0x8d, + 0x80, 0xbb, 0xeb, 0xa0, 0x37, 0x00, 0x05, 0x22, 0x6d, 0xf8, 0x55, 0xe2, 0x0b, 0xad, 0x16, 0x9b, + 0xbb, 0x62, 0x72, 0x24, 0xdc, 0xec, 0xc2, 0xc0, 0x19, 0xb5, 0x52, 0x61, 0x13, 0x46, 0xf2, 0xc3, + 0x26, 0xf4, 0x3e, 0x17, 0xfb, 0x09, 0xb2, 0xed, 0xff, 0x6c, 0xd1, 0xeb, 0x8b, 0x33, 0xf9, 0x66, + 0xf4, 0xaf, 0x57, 0x99, 0x41, 0x17, 0x97, 0xe1, 0x69, 0x11, 0x0c, 0xce, 0x68, 0x06, 0x5d, 0x09, + 0x10, 0x9b, 0xb8, 0x7c, 0x41, 0x44, 0x89, 0xe3, 0x9c, 0xc1, 0xe2, 0x8b, 0x10, 0x25, 0x0a, 0x03, + 0x7d, 0x16, 0x46, 0x5d, 0x6f, 0xcf, 0x8b, 0x82, 0x50, 0xac, 0xf4, 0x23, 0xaa, 0x0b, 0x92, 0x73, + 0xb0, 0xc2, 0xc9, 0x60, 0x49, 0xcf, 0xfe, 0x81, 0x02, 0x4c, 0xc8, 0x16, 0xdf, 0xec, 0x04, 0xb1, + 0x73, 0x02, 0xd7, 0xf2, 0x55, 0xe3, 0x5a, 0xfe, 0x58, 0xaf, 0x38, 0x2d, 0xac, 0x4b, 0xb9, 0xd7, + 0xf1, 0xcd, 0xd4, 0x75, 0xfc, 0x64, 0x7f, 0x52, 0xbd, 0xaf, 0xe1, 0x7f, 0x62, 0xc1, 0x8c, 0x81, + 0x7f, 0x02, 0xb7, 0xc1, 0xaa, 0x79, 0x1b, 0x3c, 0xde, 0xf7, 0x1b, 0x72, 0x6e, 0x81, 0xef, 0x29, + 0xa6, 0xfa, 0xce, 0x4e, 0xff, 0x77, 0x61, 0x68, 0xc7, 0x09, 0xdd, 0x5e, 0x81, 0xa9, 0xbb, 0x2a, + 0x2d, 0x5c, 0x73, 0x42, 0xa1, 0xd6, 0x7b, 0x46, 0x65, 0xbd, 0x75, 0xc2, 0xfe, 0x2a, 0x3d, 0xd6, + 0x14, 0x7a, 0x05, 0x46, 0xa2, 0x46, 0xd0, 0x56, 0x56, 0xdc, 0x17, 0x79, 0x46, 0x5c, 0x5a, 0x72, + 0x78, 0x30, 0x8f, 0xcc, 0xe6, 0x68, 0x31, 0x16, 0xf8, 0xe8, 0x2d, 0x98, 0x60, 0xbf, 0x94, 0x8d, + 0x4d, 0x31, 0x3f, 0x1d, 0x4a, 0x5d, 0x47, 0xe4, 0x06, 0x68, 0x46, 0x11, 0x36, 0x49, 0xcd, 0x6d, + 0x43, 0x59, 0x7d, 0xd6, 0x43, 0xd5, 0xc7, 0xfd, 0xfb, 0x22, 0x9c, 0xca, 0x58, 0x73, 0x28, 0x32, + 0x66, 0xe2, 0xb9, 0x01, 0x97, 0xea, 0xfb, 0x9c, 0x8b, 0x88, 0xbd, 0x86, 0x5c, 0xb1, 0xb6, 0x06, + 0x6e, 0xf4, 0x56, 0x44, 0xd2, 0x8d, 0xd2, 0xa2, 0xfe, 0x8d, 0xd2, 0xc6, 0x4e, 0x6c, 0xa8, 0x69, + 0x43, 0xaa, 0xa7, 0x0f, 0x75, 0x4e, 0xff, 0xac, 0x08, 0xa7, 0xb3, 0x42, 0x47, 0xa1, 0x6f, 0x4f, + 0xa5, 0xc6, 0x7a, 0x71, 0xd0, 0xa0, 0x53, 0x3c, 0x5f, 0x96, 0xc8, 0x6c, 0xbf, 0x60, 0x26, 0xcb, + 0xea, 0x3b, 0xcc, 0xa2, 0x4d, 0xe6, 0x14, 0x1e, 0xf2, 0x94, 0x66, 0xf2, 0xf8, 0xf8, 0xe4, 0xc0, + 0x1d, 0x10, 0xb9, 0xd0, 0xa2, 0x94, 0xfe, 0x5e, 0x16, 0xf7, 0xd7, 0xdf, 0xcb, 0x96, 0xe7, 0x3c, + 0x18, 0xd3, 0xbe, 0xe6, 0xa1, 0xce, 0xf8, 0x2e, 0xbd, 0xad, 0xb4, 0x7e, 0x3f, 0xd4, 0x59, 0xff, + 0x51, 0x0b, 0x52, 0xd6, 0xd0, 0x4a, 0x2c, 0x66, 0xe5, 0x8a, 0xc5, 0x2e, 0xc2, 0x50, 0x18, 0x34, + 0x49, 0x3a, 0x13, 0x15, 0x0e, 0x9a, 0x04, 0x33, 0x08, 0xc5, 0x88, 0x13, 0x61, 0xc7, 0xb8, 0xfe, + 0x90, 0x13, 0x4f, 0xb4, 0x27, 0x60, 0xb8, 0x49, 0xf6, 0x48, 0x33, 0x9d, 0xe6, 0xe1, 0x06, 0x2d, + 0xc4, 0x1c, 0x66, 0xff, 0xe2, 0x10, 0x9c, 0xef, 0x19, 0x56, 0x81, 0x3e, 0x87, 0xb6, 0x9d, 0x98, + 0xdc, 0x75, 0xf6, 0xd3, 0xf1, 0xd8, 0xaf, 0xf2, 0x62, 0x2c, 0xe1, 0xcc, 0x8b, 0x84, 0x47, 0x55, + 0x4d, 0x09, 0x11, 0x45, 0x30, 0x55, 0x01, 0x35, 0x85, 0x52, 0xc5, 0xe3, 0x10, 0x4a, 0x3d, 0x0f, + 0x10, 0x45, 0x4d, 0x6e, 0xf8, 0xe2, 0x0a, 0xf7, 0x94, 0x24, 0xfa, 0x6e, 0xfd, 0x86, 0x80, 0x60, + 0x0d, 0x0b, 0x55, 0x60, 0xba, 0x1d, 0x06, 0x31, 0x97, 0xc9, 0x56, 0xb8, 0x6d, 0xd8, 0xb0, 0xe9, + 0xd1, 0x5e, 0x4b, 0xc1, 0x71, 0x57, 0x0d, 0xf4, 0x12, 0x8c, 0x09, 0x2f, 0xf7, 0x5a, 0x10, 0x34, + 0x85, 0x18, 0x48, 0x99, 0x4b, 0xd5, 0x13, 0x10, 0xd6, 0xf1, 0xb4, 0x6a, 0x4c, 0xd0, 0x3b, 0x9a, + 0x59, 0x8d, 0x0b, 0x7b, 0x35, 0xbc, 0x54, 0x18, 0xb9, 0xd2, 0x40, 0x61, 0xe4, 0x12, 0xc1, 0x58, + 0x79, 0x60, 0xdd, 0x16, 0xf4, 0x15, 0x25, 0xfd, 0xfc, 0x10, 0x9c, 0x12, 0x0b, 0xe7, 0x61, 0x2f, + 0x97, 0x5b, 0xdd, 0xcb, 0xe5, 0x38, 0x44, 0x67, 0x1f, 0xae, 0x99, 0x93, 0x5e, 0x33, 0x3f, 0x68, + 0x81, 0xc9, 0x5e, 0xa1, 0xff, 0x2b, 0x37, 0xa1, 0xc5, 0x4b, 0xb9, 0xec, 0x9a, 0x2b, 0x2f, 0x90, + 0xf7, 0x99, 0xda, 0xc2, 0xfe, 0x4f, 0x16, 0x3c, 0xde, 0x97, 0x22, 0x5a, 0x81, 0x32, 0xe3, 0x01, + 0xb5, 0xd7, 0xd9, 0x93, 0xca, 0x76, 0x54, 0x02, 0x72, 0x58, 0xd2, 0xa4, 0x26, 0x5a, 0xe9, 0xca, + 0x1c, 0xf2, 0x54, 0x46, 0xe6, 0x90, 0x33, 0xc6, 0xf0, 0x3c, 0x60, 0xea, 0x90, 0x5f, 0x29, 0xc2, + 0x08, 0x5f, 0xf1, 0x27, 0xf0, 0x0c, 0x5b, 0x15, 0x72, 0xdb, 0x1e, 0x71, 0xea, 0x78, 0x5f, 0x16, + 0x2a, 0x4e, 0xec, 0x70, 0x36, 0x41, 0xdd, 0x56, 0x89, 0x84, 0x17, 0x7d, 0x1e, 0x20, 0x8a, 0x43, + 0xcf, 0xdf, 0xa6, 0x65, 0x22, 0x82, 0xe1, 0xc7, 0x7b, 0x50, 0xab, 0x2b, 0x64, 0x4e, 0x33, 0xd9, + 0xb9, 0x0a, 0x80, 0x35, 0x8a, 0x68, 0xc1, 0xb8, 0x2f, 0xe7, 0x52, 0x82, 0x4f, 0xe0, 0x54, 0x93, + 0xdb, 0x73, 0xee, 0x65, 0x28, 0x2b, 0xe2, 0xfd, 0xa4, 0x38, 0xe3, 0x3a, 0x73, 0xf1, 0x69, 0x98, + 0x4a, 0xf5, 0xed, 0x48, 0x42, 0xa0, 0x5f, 0xb2, 0x60, 0x8a, 0x77, 0x66, 0xc5, 0xdf, 0x13, 0x67, + 0xea, 0x7b, 0x70, 0xba, 0x99, 0x71, 0xb6, 0x89, 0x19, 0x1d, 0xfc, 0x2c, 0x54, 0x42, 0x9f, 0x2c, + 0x28, 0xce, 0x6c, 0x03, 0x5d, 0xa6, 0xeb, 0x96, 0x9e, 0x5d, 0x4e, 0x53, 0x38, 0x1b, 0x8e, 0xf3, + 0x35, 0xcb, 0xcb, 0xb0, 0x82, 0xda, 0xbf, 0x63, 0xc1, 0x0c, 0xef, 0xf9, 0x75, 0xb2, 0xaf, 0x76, + 0xf8, 0xd7, 0xb3, 0xef, 0x22, 0x99, 0x4f, 0x21, 0x27, 0x99, 0x8f, 0xfe, 0x69, 0xc5, 0x9e, 0x9f, + 0xf6, 0xb3, 0x16, 0x88, 0x15, 0x72, 0x02, 0x4f, 0xf9, 0x6f, 0x36, 0x9f, 0xf2, 0x73, 0xf9, 0x9b, + 0x20, 0xe7, 0x0d, 0xff, 0x17, 0x16, 0x4c, 0x73, 0x84, 0x44, 0xe7, 0xfc, 0x75, 0x9d, 0x87, 0x41, + 0xb2, 0x72, 0xaa, 0x54, 0xfd, 0xd9, 0x1f, 0x65, 0x4c, 0xd6, 0x50, 0xcf, 0xc9, 0x72, 0xe5, 0x06, + 0x3a, 0x42, 0x46, 0xda, 0x23, 0x87, 0xba, 0xb7, 0xff, 0xc8, 0x02, 0xc4, 0x9b, 0x31, 0xd8, 0x1f, + 0xca, 0x54, 0xb0, 0x52, 0xed, 0xba, 0x48, 0x8e, 0x26, 0x05, 0xc1, 0x1a, 0xd6, 0xb1, 0x0c, 0x4f, + 0xca, 0x70, 0xa0, 0xd8, 0xdf, 0x70, 0xe0, 0x08, 0x23, 0xfa, 0x87, 0xc3, 0x90, 0xf6, 0x00, 0x41, + 0xb7, 0x61, 0xbc, 0xe1, 0xb4, 0x9d, 0x4d, 0xaf, 0xe9, 0xc5, 0x1e, 0x89, 0x7a, 0x59, 0x1c, 0x2d, + 0x6b, 0x78, 0x42, 0xd5, 0xab, 0x95, 0x60, 0x83, 0x0e, 0x5a, 0x00, 0x68, 0x87, 0xde, 0x9e, 0xd7, + 0x24, 0xdb, 0x4c, 0xe2, 0xc0, 0xdc, 0x9b, 0xb9, 0x19, 0x8d, 0x2c, 0xc5, 0x1a, 0x46, 0x86, 0xa7, + 0x6a, 0xf1, 0x21, 0x7b, 0xaa, 0xc2, 0x89, 0x79, 0xaa, 0x0e, 0x1d, 0xc9, 0x53, 0xb5, 0x74, 0x64, + 0x4f, 0xd5, 0xe1, 0x81, 0x3c, 0x55, 0x31, 0x9c, 0x95, 0x1c, 0x1c, 0xfd, 0xbf, 0xea, 0x35, 0x89, + 0x60, 0xdb, 0xb9, 0x4f, 0xf6, 0xdc, 0xfd, 0x83, 0xf9, 0xb3, 0x38, 0x13, 0x03, 0xe7, 0xd4, 0x44, + 0x9f, 0x81, 0x59, 0xa7, 0xd9, 0x0c, 0xee, 0xaa, 0x49, 0x5d, 0x89, 0x1a, 0x4e, 0x93, 0x8b, 0xf2, + 0x47, 0x19, 0xd5, 0xc7, 0xee, 0x1f, 0xcc, 0xcf, 0x2e, 0xe6, 0xe0, 0xe0, 0xdc, 0xda, 0xe8, 0x35, + 0x28, 0xb7, 0xc3, 0xa0, 0xb1, 0xa6, 0xb9, 0xa9, 0x5d, 0xa0, 0x03, 0x58, 0x93, 0x85, 0x87, 0x07, + 0xf3, 0x13, 0xea, 0x0f, 0xbb, 0xf0, 0x93, 0x0a, 0xf6, 0x2e, 0x9c, 0xaa, 0x93, 0xd0, 0x63, 0x89, + 0x7b, 0xdd, 0xe4, 0xfc, 0xd8, 0x80, 0x72, 0x98, 0x3a, 0x31, 0x07, 0x8a, 0xed, 0xa6, 0xc5, 0x04, + 0x97, 0x27, 0x64, 0x42, 0xc8, 0xfe, 0x9f, 0x16, 0x8c, 0x0a, 0x8f, 0x8c, 0x13, 0x60, 0xd4, 0x16, + 0x0d, 0x79, 0xf9, 0x7c, 0xf6, 0xad, 0xc2, 0x3a, 0x93, 0x2b, 0x29, 0xaf, 0xa6, 0x24, 0xe5, 0x8f, + 0xf7, 0x22, 0xd2, 0x5b, 0x46, 0xfe, 0x37, 0x8b, 0x30, 0x69, 0xba, 0xee, 0x9d, 0xc0, 0x10, 0xac, + 0xc3, 0x68, 0x24, 0x7c, 0xd3, 0x0a, 0xf9, 0x16, 0xd9, 0xe9, 0x49, 0x4c, 0xac, 0xb5, 0x84, 0x37, + 0x9a, 0x24, 0x92, 0xe9, 0xf4, 0x56, 0x7c, 0x88, 0x4e, 0x6f, 0xfd, 0xbc, 0x27, 0x87, 0x8e, 0xc3, + 0x7b, 0xd2, 0xfe, 0x2a, 0xbb, 0xd9, 0xf4, 0xf2, 0x13, 0x60, 0x7a, 0xae, 0x9a, 0x77, 0xa0, 0xdd, + 0x63, 0x65, 0x89, 0x4e, 0xe5, 0x30, 0x3f, 0xbf, 0x60, 0xc1, 0xf9, 0x8c, 0xaf, 0xd2, 0x38, 0xa1, + 0x67, 0xa0, 0xe4, 0x74, 0x5c, 0x4f, 0xed, 0x65, 0x4d, 0x6b, 0xb6, 0x28, 0xca, 0xb1, 0xc2, 0x40, + 0xcb, 0x30, 0x43, 0xee, 0xb5, 0x3d, 0xae, 0x30, 0xd4, 0x4d, 0x2a, 0x8b, 0x3c, 0xde, 0xf5, 0x4a, + 0x1a, 0x88, 0xbb, 0xf1, 0x55, 0xb0, 0x87, 0x62, 0x6e, 0xb0, 0x87, 0xbf, 0x6f, 0xc1, 0x98, 0xf2, + 0xce, 0x7a, 0xe8, 0xa3, 0xfd, 0x2d, 0xe6, 0x68, 0x3f, 0xda, 0x63, 0xb4, 0x73, 0x86, 0xf9, 0x6f, + 0x17, 0x54, 0x7f, 0x6b, 0x41, 0x18, 0x0f, 0xc0, 0x61, 0xbd, 0x02, 0xa5, 0x76, 0x18, 0xc4, 0x41, + 0x23, 0x68, 0x0a, 0x06, 0xeb, 0xb1, 0x24, 0x16, 0x09, 0x2f, 0x3f, 0xd4, 0x7e, 0x63, 0x85, 0xcd, + 0x46, 0x2f, 0x08, 0x63, 0xc1, 0xd4, 0x24, 0xa3, 0x17, 0x84, 0x31, 0x66, 0x10, 0xe4, 0x02, 0xc4, + 0x4e, 0xb8, 0x4d, 0x62, 0x5a, 0x26, 0x62, 0x1f, 0xe5, 0x1f, 0x1e, 0x9d, 0xd8, 0x6b, 0x2e, 0x78, + 0x7e, 0x1c, 0xc5, 0xe1, 0x42, 0xd5, 0x8f, 0x6f, 0x86, 0xfc, 0xbd, 0xa6, 0x05, 0x17, 0x51, 0xb4, + 0xb0, 0x46, 0x57, 0xba, 0x15, 0xb3, 0x36, 0x86, 0x4d, 0xfd, 0xfb, 0xba, 0x28, 0xc7, 0x0a, 0xc3, + 0x7e, 0x99, 0x5d, 0x25, 0x6c, 0x80, 0x8e, 0x16, 0xf7, 0xe3, 0xbb, 0xcb, 0x6a, 0x68, 0x99, 0xf2, + 0xad, 0xa2, 0x47, 0x17, 0xe9, 0x7d, 0x72, 0xd3, 0x86, 0x75, 0x17, 0xa3, 0x24, 0x04, 0x09, 0xfa, + 0xd6, 0x2e, 0x9b, 0x8a, 0x67, 0xfb, 0x5c, 0x01, 0x47, 0xb0, 0xa2, 0x60, 0x31, 0xf8, 0x59, 0x84, + 0xf2, 0x6a, 0x4d, 0x2c, 0x72, 0x2d, 0x06, 0xbf, 0x00, 0xe0, 0x04, 0x07, 0x5d, 0x11, 0xaf, 0xf1, + 0x21, 0x23, 0xf3, 0xa4, 0x7c, 0x8d, 0xcb, 0xcf, 0xd7, 0x84, 0xd9, 0xcf, 0xc1, 0x98, 0xca, 0x40, + 0x59, 0xe3, 0x89, 0x0d, 0x45, 0x24, 0xa8, 0x95, 0xa4, 0x18, 0xeb, 0x38, 0x68, 0x03, 0xa6, 0x22, + 0x2e, 0xea, 0x51, 0x01, 0x3f, 0xb9, 0xc8, 0xec, 0xe3, 0xd2, 0x10, 0xa5, 0x6e, 0x82, 0x0f, 0x59, + 0x11, 0x3f, 0x3a, 0xa4, 0x2b, 0x6f, 0x9a, 0x04, 0x7a, 0x1d, 0x26, 0x9b, 0x81, 0xe3, 0x2e, 0x39, + 0x4d, 0xc7, 0x6f, 0xb0, 0xef, 0x2d, 0x99, 0x89, 0xcc, 0x6e, 0x18, 0x50, 0x9c, 0xc2, 0xa6, 0x9c, + 0x8f, 0x5e, 0x22, 0x82, 0xd4, 0x3a, 0xfe, 0x36, 0x89, 0x44, 0x3e, 0x41, 0xc6, 0xf9, 0xdc, 0xc8, + 0xc1, 0xc1, 0xb9, 0xb5, 0xd1, 0x2b, 0x30, 0x2e, 0x3f, 0x5f, 0xf3, 0x7c, 0x4f, 0x6c, 0xef, 0x35, + 0x18, 0x36, 0x30, 0xd1, 0x5d, 0x38, 0x23, 0xff, 0x6f, 0x84, 0xce, 0xd6, 0x96, 0xd7, 0x10, 0xee, + 0xa0, 0xdc, 0x31, 0x6e, 0x51, 0x7a, 0x6f, 0xad, 0x64, 0x21, 0x1d, 0x1e, 0xcc, 0x5f, 0x14, 0xa3, + 0x96, 0x09, 0x67, 0x93, 0x98, 0x4d, 0x1f, 0xad, 0xc1, 0xa9, 0x1d, 0xe2, 0x34, 0xe3, 0x9d, 0xe5, + 0x1d, 0xd2, 0xd8, 0x95, 0x9b, 0x88, 0xf9, 0xd3, 0x6b, 0x16, 0xeb, 0xd7, 0xba, 0x51, 0x70, 0x56, + 0x3d, 0xf4, 0x36, 0xcc, 0xb6, 0x3b, 0x9b, 0x4d, 0x2f, 0xda, 0x59, 0x0f, 0x62, 0x66, 0x8d, 0xa2, + 0x12, 0x5a, 0x0a, 0xc7, 0x7b, 0x15, 0xb1, 0xa0, 0x96, 0x83, 0x87, 0x73, 0x29, 0xa0, 0xf7, 0xe0, + 0x4c, 0x6a, 0x31, 0x08, 0xd7, 0xe3, 0xc9, 0xfc, 0x90, 0xdf, 0xf5, 0xac, 0x0a, 0xc2, 0x8b, 0x3f, + 0x0b, 0x84, 0xb3, 0x9b, 0x40, 0x2f, 0x42, 0xc9, 0x6b, 0xaf, 0x3a, 0x2d, 0xaf, 0xb9, 0xcf, 0x62, + 0x96, 0x97, 0x59, 0x1c, 0xef, 0x52, 0xb5, 0xc6, 0xcb, 0x0e, 0xb5, 0xdf, 0x58, 0x61, 0xbe, 0x3f, + 0x6b, 0xa4, 0x77, 0x69, 0x65, 0x8d, 0x95, 0x43, 0x5f, 0x80, 0x71, 0x7d, 0xed, 0x89, 0x6b, 0xe9, + 0x52, 0x36, 0xa7, 0xa3, 0xad, 0x51, 0xce, 0x08, 0xaa, 0x75, 0xa8, 0xc3, 0xb0, 0x41, 0xd1, 0x26, + 0x90, 0x3d, 0x2a, 0xe8, 0x06, 0x94, 0x1a, 0x4d, 0x8f, 0xf8, 0x71, 0xb5, 0xd6, 0x2b, 0x10, 0xd1, + 0xb2, 0xc0, 0x11, 0xc3, 0x2c, 0x22, 0x2b, 0xf3, 0x32, 0xac, 0x28, 0xd8, 0xbf, 0x56, 0x80, 0xf9, + 0x3e, 0x61, 0xba, 0x53, 0x42, 0x73, 0x6b, 0x20, 0xa1, 0xf9, 0xa2, 0x4c, 0xea, 0xb9, 0x9e, 0x92, + 0x24, 0xa4, 0x12, 0x76, 0x26, 0xf2, 0x84, 0x34, 0xfe, 0xc0, 0x46, 0xcc, 0xba, 0xdc, 0x7d, 0xa8, + 0xaf, 0x19, 0xbe, 0xa1, 0x6f, 0x1b, 0x1e, 0xfc, 0xf9, 0x92, 0xab, 0x3b, 0xb1, 0xbf, 0x5a, 0x80, + 0x33, 0x6a, 0x08, 0xbf, 0x71, 0x07, 0xee, 0x56, 0xf7, 0xc0, 0x1d, 0x83, 0xe6, 0xc9, 0xbe, 0x09, + 0x23, 0x3c, 0xb2, 0xd2, 0x00, 0x6c, 0xd3, 0x13, 0x66, 0x68, 0x40, 0x75, 0xb9, 0x1b, 0xe1, 0x01, + 0xbf, 0xcf, 0x82, 0xa9, 0x8d, 0xe5, 0x5a, 0x3d, 0x68, 0xec, 0x92, 0x78, 0x91, 0xb3, 0xb9, 0x58, + 0x70, 0x4d, 0xd6, 0x03, 0x72, 0x43, 0x59, 0x7c, 0xd6, 0x45, 0x18, 0xda, 0x09, 0xa2, 0x38, 0xad, + 0x96, 0xbe, 0x16, 0x44, 0x31, 0x66, 0x10, 0xfb, 0x77, 0x2d, 0x18, 0x66, 0x79, 0xac, 0xfb, 0x65, + 0x52, 0x1f, 0xe4, 0xbb, 0xd0, 0x4b, 0x30, 0x42, 0xb6, 0xb6, 0x48, 0x23, 0x16, 0xb3, 0x2a, 0xfd, + 0x88, 0x47, 0x56, 0x58, 0x29, 0x65, 0x15, 0x58, 0x63, 0xfc, 0x2f, 0x16, 0xc8, 0xe8, 0x0e, 0x94, + 0x63, 0xaf, 0x45, 0x16, 0x5d, 0x57, 0x28, 0xf6, 0x1e, 0xc0, 0x17, 0x7a, 0x43, 0x12, 0xc0, 0x09, + 0x2d, 0xfb, 0xcb, 0x05, 0x80, 0x24, 0xae, 0x46, 0xbf, 0x4f, 0x5c, 0xea, 0x52, 0xf9, 0x5c, 0xca, + 0x50, 0xf9, 0xa0, 0x84, 0x60, 0x86, 0xbe, 0x47, 0x0d, 0x53, 0x71, 0xa0, 0x61, 0x1a, 0x3a, 0xca, + 0x30, 0x2d, 0xc3, 0x4c, 0x12, 0x17, 0xc4, 0x0c, 0x8b, 0xc4, 0x9e, 0x36, 0x1b, 0x69, 0x20, 0xee, + 0xc6, 0xb7, 0x09, 0x5c, 0x54, 0xe1, 0x11, 0xc4, 0x5d, 0xc3, 0xec, 0x46, 0x8f, 0x90, 0x54, 0x3f, + 0xd1, 0x69, 0x15, 0x72, 0x75, 0x5a, 0x3f, 0x61, 0xc1, 0xe9, 0x74, 0x3b, 0xcc, 0x91, 0xef, 0x4b, + 0x16, 0x9c, 0x61, 0x9a, 0x3d, 0xd6, 0x6a, 0xb7, 0x1e, 0xf1, 0xc5, 0x9e, 0x21, 0x1f, 0x72, 0x7a, + 0x9c, 0x38, 0xac, 0xaf, 0x65, 0x91, 0xc6, 0xd9, 0x2d, 0xda, 0xff, 0xb1, 0x00, 0xb3, 0x79, 0xb1, + 0x22, 0x98, 0x59, 0xb9, 0x73, 0xaf, 0xbe, 0x4b, 0xee, 0x0a, 0xe3, 0xdd, 0xc4, 0xac, 0x9c, 0x17, + 0x63, 0x09, 0x4f, 0x47, 0x5e, 0x2e, 0x0c, 0x16, 0x79, 0x19, 0xed, 0xc0, 0xcc, 0xdd, 0x1d, 0xe2, + 0xdf, 0xf2, 0x23, 0x27, 0xf6, 0xa2, 0x2d, 0x8f, 0x65, 0x44, 0xe7, 0xeb, 0xe6, 0x53, 0xd2, 0xc4, + 0xf6, 0x4e, 0x1a, 0xe1, 0xf0, 0x60, 0xfe, 0xbc, 0x51, 0x90, 0x74, 0x99, 0x1f, 0x24, 0xb8, 0x9b, + 0x68, 0x77, 0xe0, 0xea, 0xa1, 0x87, 0x18, 0xb8, 0xda, 0xfe, 0x92, 0x05, 0xe7, 0x72, 0x13, 0xcb, + 0xa1, 0xcb, 0x50, 0x72, 0xda, 0x1e, 0x17, 0x81, 0x8a, 0x63, 0x94, 0x3d, 0xe5, 0x6b, 0x55, 0x2e, + 0x00, 0x55, 0x50, 0x95, 0xf0, 0xb6, 0x90, 0x9b, 0xf0, 0xb6, 0x6f, 0xfe, 0x5a, 0xfb, 0x7b, 0x2d, + 0x10, 0x2e, 0x71, 0x03, 0x9c, 0xdd, 0x6f, 0xc9, 0x7c, 0xe1, 0x46, 0x72, 0x8b, 0x8b, 0xf9, 0x3e, + 0x82, 0x22, 0xa5, 0x85, 0xe2, 0x95, 0x8c, 0x44, 0x16, 0x06, 0x2d, 0xdb, 0x05, 0x01, 0xad, 0x10, + 0x26, 0x40, 0xec, 0xdf, 0x9b, 0xe7, 0x01, 0x5c, 0x86, 0xab, 0x65, 0x0d, 0x56, 0x37, 0x73, 0x45, + 0x41, 0xb0, 0x86, 0x65, 0xff, 0xdb, 0x02, 0x8c, 0xc9, 0x64, 0x0a, 0x1d, 0x7f, 0x90, 0x67, 0xfe, + 0x91, 0xb2, 0xab, 0xb1, 0x34, 0xdb, 0x94, 0x70, 0x2d, 0x91, 0x8e, 0x24, 0x69, 0xb6, 0x25, 0x00, + 0x27, 0x38, 0x74, 0x17, 0x45, 0x9d, 0x4d, 0x86, 0x9e, 0x72, 0xe0, 0xaa, 0xf3, 0x62, 0x2c, 0xe1, + 0xe8, 0x33, 0x30, 0xcd, 0xeb, 0x85, 0x41, 0xdb, 0xd9, 0xe6, 0xb2, 0xe5, 0x61, 0xe5, 0x79, 0x3d, + 0xbd, 0x96, 0x82, 0x1d, 0x1e, 0xcc, 0x9f, 0x4e, 0x97, 0x31, 0xa5, 0x49, 0x17, 0x15, 0x66, 0x88, + 0xc1, 0x1b, 0xa1, 0xbb, 0xbf, 0xcb, 0x7e, 0x23, 0x01, 0x61, 0x1d, 0xcf, 0xfe, 0x02, 0xa0, 0xee, + 0xb4, 0x12, 0xe8, 0x0d, 0x6e, 0x7d, 0xe7, 0x85, 0xc4, 0xed, 0xa5, 0x44, 0xd1, 0xfd, 0x8b, 0xa5, + 0xef, 0x05, 0xaf, 0x85, 0x55, 0x7d, 0xfb, 0xff, 0x2b, 0xc2, 0x74, 0xda, 0xdb, 0x14, 0x5d, 0x83, + 0x11, 0xce, 0x7a, 0x08, 0xf2, 0x3d, 0x74, 0xf4, 0x9a, 0x8f, 0x2a, 0x3b, 0x84, 0x05, 0xf7, 0x22, + 0xea, 0xa3, 0xb7, 0x61, 0xcc, 0x0d, 0xee, 0xfa, 0x77, 0x9d, 0xd0, 0x5d, 0xac, 0x55, 0xc5, 0x72, + 0xce, 0x7c, 0xf7, 0x54, 0x12, 0x34, 0xdd, 0xef, 0x95, 0xe9, 0xa3, 0x12, 0x10, 0xd6, 0xc9, 0xa1, + 0x0d, 0x16, 0x05, 0x77, 0xcb, 0xdb, 0x5e, 0x73, 0xda, 0xbd, 0x4c, 0xb1, 0x97, 0x25, 0x92, 0x46, + 0x79, 0x42, 0x84, 0xca, 0xe5, 0x00, 0x9c, 0x10, 0x42, 0xdf, 0x0e, 0xa7, 0xa2, 0x1c, 0x51, 0x69, + 0x5e, 0x96, 0xa1, 0x5e, 0xd2, 0xc3, 0xa5, 0x47, 0xe8, 0x8b, 0x34, 0x4b, 0xa8, 0x9a, 0xd5, 0x8c, + 0xfd, 0xeb, 0xa7, 0xc0, 0xd8, 0xc4, 0x46, 0xd2, 0x39, 0xeb, 0x98, 0x92, 0xce, 0x61, 0x28, 0x91, + 0x56, 0x3b, 0xde, 0xaf, 0x78, 0x61, 0xaf, 0xac, 0xa5, 0x2b, 0x02, 0xa7, 0x9b, 0xa6, 0x84, 0x60, + 0x45, 0x27, 0x3b, 0x33, 0x60, 0xf1, 0xeb, 0x98, 0x19, 0x70, 0xe8, 0x04, 0x33, 0x03, 0xae, 0xc3, + 0xe8, 0xb6, 0x17, 0x63, 0xd2, 0x0e, 0x04, 0xd3, 0x9f, 0xb9, 0x0e, 0xaf, 0x72, 0x94, 0xee, 0x1c, + 0x54, 0x02, 0x80, 0x25, 0x11, 0xf4, 0x86, 0xda, 0x81, 0x23, 0xf9, 0x6f, 0xe6, 0x6e, 0x65, 0x72, + 0xe6, 0x1e, 0x14, 0xf9, 0xff, 0x46, 0x1f, 0x34, 0xff, 0xdf, 0xaa, 0xcc, 0xda, 0x57, 0xca, 0xf7, + 0x9b, 0x60, 0x49, 0xf9, 0xfa, 0xe4, 0xea, 0xbb, 0xad, 0x67, 0x3a, 0x2c, 0xe7, 0x9f, 0x04, 0x2a, + 0x89, 0xe1, 0x80, 0xf9, 0x0d, 0xbf, 0xd7, 0x82, 0x33, 0xed, 0xac, 0xa4, 0x9f, 0x42, 0xef, 0xfa, + 0xd2, 0xc0, 0x59, 0x4d, 0x8d, 0x06, 0x99, 0xc8, 0x25, 0x13, 0x0d, 0x67, 0x37, 0x47, 0x07, 0x3a, + 0xdc, 0x74, 0x45, 0x82, 0xbe, 0x27, 0x72, 0x12, 0x25, 0xf6, 0x48, 0x8f, 0xb8, 0x91, 0x91, 0x94, + 0xef, 0xa3, 0x79, 0x49, 0xf9, 0x06, 0x4e, 0xc5, 0xf7, 0x86, 0x4a, 0x91, 0x38, 0x91, 0xbf, 0x94, + 0x78, 0x02, 0xc4, 0xbe, 0x89, 0x11, 0xdf, 0x50, 0x89, 0x11, 0x7b, 0x44, 0x84, 0xe4, 0x69, 0x0f, + 0xfb, 0xa6, 0x43, 0xd4, 0x52, 0x1a, 0x4e, 0x1d, 0x4f, 0x4a, 0x43, 0xe3, 0xaa, 0xe1, 0x59, 0xf5, + 0x9e, 0xee, 0x73, 0xd5, 0x18, 0x74, 0x7b, 0x5f, 0x36, 0x3c, 0x7d, 0xe3, 0xcc, 0x03, 0xa5, 0x6f, + 0xbc, 0xad, 0xa7, 0x43, 0x44, 0x7d, 0xf2, 0xfd, 0x51, 0xa4, 0x01, 0x93, 0x20, 0xde, 0xd6, 0x2f, + 0xc0, 0x53, 0xf9, 0x74, 0xd5, 0x3d, 0xd7, 0x4d, 0x37, 0xf3, 0x0a, 0xec, 0x4a, 0xae, 0x78, 0xfa, + 0x64, 0x92, 0x2b, 0x9e, 0x39, 0xf6, 0xe4, 0x8a, 0x67, 0x4f, 0x20, 0xb9, 0xe2, 0x23, 0x27, 0x98, + 0x5c, 0xf1, 0x36, 0x33, 0x56, 0xe0, 0x81, 0x45, 0x44, 0x04, 0xcb, 0xec, 0x68, 0x89, 0x59, 0xd1, + 0x47, 0xf8, 0xc7, 0x29, 0x10, 0x4e, 0x48, 0x65, 0x24, 0x6d, 0x9c, 0x7d, 0x08, 0x49, 0x1b, 0xd7, + 0x93, 0xa4, 0x8d, 0xe7, 0xf2, 0xa7, 0x3a, 0xc3, 0x48, 0x3c, 0x27, 0x55, 0xe3, 0x6d, 0x3d, 0xc5, + 0xe2, 0xa3, 0x3d, 0x84, 0xea, 0x59, 0x82, 0xc7, 0x1e, 0x89, 0x15, 0x5f, 0xe7, 0x89, 0x15, 0x1f, + 0xcb, 0x3f, 0xc9, 0xd3, 0xd7, 0x9d, 0x99, 0x4e, 0xf1, 0xfb, 0x0b, 0x70, 0xa1, 0xf7, 0xbe, 0x48, + 0xa4, 0x9e, 0xb5, 0x44, 0xb7, 0x97, 0x92, 0x7a, 0xf2, 0xb7, 0x55, 0x82, 0x35, 0x70, 0xcc, 0xa9, + 0xab, 0x30, 0xa3, 0xac, 0xc0, 0x9b, 0x5e, 0x63, 0x5f, 0xcb, 0x20, 0xaf, 0x3c, 0x67, 0xeb, 0x69, + 0x04, 0xdc, 0x5d, 0x07, 0x2d, 0xc2, 0x94, 0x51, 0x58, 0xad, 0x88, 0x37, 0x94, 0x12, 0xb3, 0xd6, + 0x4d, 0x30, 0x4e, 0xe3, 0xdb, 0x3f, 0x63, 0xc1, 0x23, 0x39, 0x79, 0x8b, 0x06, 0x0e, 0xa9, 0xb4, + 0x05, 0x53, 0x6d, 0xb3, 0x6a, 0x9f, 0xc8, 0x6b, 0x46, 0x76, 0x24, 0xd5, 0xd7, 0x14, 0x00, 0xa7, + 0x89, 0xda, 0x7f, 0x6e, 0xc1, 0xf9, 0x9e, 0x06, 0x59, 0x08, 0xc3, 0xd9, 0xed, 0x56, 0xe4, 0x2c, + 0x87, 0xc4, 0x25, 0x7e, 0xec, 0x39, 0xcd, 0x7a, 0x9b, 0x34, 0x34, 0xb9, 0x35, 0xb3, 0x6c, 0xba, + 0xba, 0x56, 0x5f, 0xec, 0xc6, 0xc0, 0x39, 0x35, 0xd1, 0x2a, 0xa0, 0x6e, 0x88, 0x98, 0x61, 0x16, + 0x9d, 0xb5, 0x9b, 0x1e, 0xce, 0xa8, 0x81, 0x5e, 0x86, 0x09, 0x65, 0xe8, 0xa5, 0xcd, 0x38, 0x3b, + 0x80, 0xb1, 0x0e, 0xc0, 0x26, 0xde, 0xd2, 0xe5, 0xdf, 0xfc, 0xfd, 0x0b, 0x1f, 0xf9, 0xed, 0xdf, + 0xbf, 0xf0, 0x91, 0xdf, 0xf9, 0xfd, 0x0b, 0x1f, 0xf9, 0xce, 0xfb, 0x17, 0xac, 0xdf, 0xbc, 0x7f, + 0xc1, 0xfa, 0xed, 0xfb, 0x17, 0xac, 0xdf, 0xb9, 0x7f, 0xc1, 0xfa, 0xbd, 0xfb, 0x17, 0xac, 0x2f, + 0xff, 0xc1, 0x85, 0x8f, 0xbc, 0x55, 0xd8, 0x7b, 0xee, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x2d, + 0xfa, 0x2a, 0x30, 0x95, 0xf9, 0x00, 0x00, } func (m *AWSElasticBlockStoreVolumeSource) Marshal() (dAtA []byte, err error) { @@ -17500,6 +17502,13 @@ func (m *ServiceSpec) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.IPFamily != nil { + i -= len(*m.IPFamily) + copy(dAtA[i:], *m.IPFamily) + i = encodeVarintGenerated(dAtA, i, uint64(len(*m.IPFamily))) + i-- + dAtA[i] = 0x7a + } if m.SessionAffinityConfig != nil { { size, err := m.SessionAffinityConfig.MarshalToSizedBuffer(dAtA[:i]) @@ -22818,6 +22827,10 @@ func (m *ServiceSpec) Size() (n int) { l = m.SessionAffinityConfig.Size() n += 1 + l + sovGenerated(uint64(l)) } + if m.IPFamily != nil { + l = len(*m.IPFamily) + n += 1 + l + sovGenerated(uint64(l)) + } return n } @@ -26314,6 +26327,7 @@ func (this *ServiceSpec) String() string { `HealthCheckNodePort:` + fmt.Sprintf("%v", this.HealthCheckNodePort) + `,`, `PublishNotReadyAddresses:` + fmt.Sprintf("%v", this.PublishNotReadyAddresses) + `,`, `SessionAffinityConfig:` + strings.Replace(this.SessionAffinityConfig.String(), "SessionAffinityConfig", "SessionAffinityConfig", 1) + `,`, + `IPFamily:` + valueToStringGenerated(this.IPFamily) + `,`, `}`, }, "") return s @@ -61629,6 +61643,39 @@ func (m *ServiceSpec) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IPFamily", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenerated + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenerated + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + s := IPFamily(dAtA[iNdEx:postIndex]) + m.IPFamily = &s + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 5dcc244f1b5..2ee31d360b9 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -4669,6 +4669,16 @@ message ServiceSpec { // sessionAffinityConfig contains the configurations of session affinity. // +optional optional SessionAffinityConfig sessionAffinityConfig = 14; + + // ipFamily specifies whether this Service has a preference for a particular IP family (e.g. IPv4 vs. + // IPv6). If a specific IP family is requested, the clusterIP field will be allocated from that family, if it is + // available in the cluster. If no IP family is requested, the cluster's primary IP family will be used. + // Other IP fields (loadBalancerIP, loadBalancerSourceRanges, externalIPs) and controllers which + // allocate external load-balancers should use the same IP family. Endpoints for this Service will be of + // this family. This field is immutable after creation. Assigning a ServiceIPFamily not available in the + // cluster (e.g. IPv6 in IPv4 only cluster) is an error condition and will fail during clusterIP assignment. + // +optional + optional string ipFamily = 15; } // ServiceStatus represents the current status of a service. diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 6058117637b..75c7c2059ca 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -2187,6 +2187,7 @@ var map_ServiceSpec = map[string]string{ "healthCheckNodePort": "healthCheckNodePort specifies the healthcheck nodePort for the service. If not specified, HealthCheckNodePort is created by the service api backend with the allocated nodePort. Will use user-specified nodePort value if specified by the client. Only effects when Type is set to LoadBalancer and ExternalTrafficPolicy is set to Local.", "publishNotReadyAddresses": "publishNotReadyAddresses, when set to true, indicates that DNS implementations must publish the notReadyAddresses of subsets for the Endpoints associated with the Service. The default value is false. The primary use case for setting this field is to use a StatefulSet's Headless Service to propagate SRV records for its Pods without respect to their readiness for purpose of peer discovery.", "sessionAffinityConfig": "sessionAffinityConfig contains the configurations of session affinity.", + "ipFamily": "ipFamily specifies whether this Service has a preference for a particular IP family (e.g. IPv4 vs. IPv6). If a specific IP family is requested, the clusterIP field will be allocated from that family, if it is available in the cluster. If no IP family is requested, the cluster's primary IP family will be used. Other IP fields (loadBalancerIP, loadBalancerSourceRanges, externalIPs) and controllers which allocate external load-balancers should use the same IP family. Endpoints for this Service will be of this family. This field is immutable after creation. Assigning a ServiceIPFamily not available in the cluster (e.g. IPv6 in IPv4 only cluster) is an error condition and will fail during clusterIP assignment.", } func (ServiceSpec) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go b/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go index 02d36058b17..5806247ef77 100644 --- a/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/core/v1/zz_generated.deepcopy.go @@ -5142,6 +5142,11 @@ func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) { *out = new(SessionAffinityConfig) (*in).DeepCopyInto(*out) } + if in.IPFamily != nil { + in, out := &in.IPFamily, &out.IPFamily + *out = new(IPFamily) + **out = **in + } return } diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.json b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.json index beef1c47a3c..28daaafba50 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.json +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.json @@ -71,7 +71,8 @@ "clientIP": { "timeoutSeconds": -1973740160 } - } + }, + "ipFamily": "³-Ǐ忄*齧獚敆ȎțêɘIJ斬" }, "status": { "loadBalancer": { diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.pb b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.pb index f2a9b5148773bf6f9744227f6f42daa557e452cb..24f1972253c023edd3cc76ade0f7d984ead6ae18 100644 GIT binary patch delta 68 zcmV-K0K5P20+9od6an{<6|Mogk;IxadLP2GEys`Lzl193y{G4mn&y>;$d1UH!>Y-c a#Ioj=tQrgo3JM4c0x~!f0x~%o03raI=pHoy delta 35 rcmbQp{DEnL2;;ShqU#uEPCPP8NQ#Gxi;IJc$;d*8$;eWQL5TqX#o7pN diff --git a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.yaml b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.yaml index 4cb42f908cd..02b6d48da6a 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/core.v1.Service.yaml @@ -36,6 +36,7 @@ spec: externalName: "27" externalTrafficPolicy: ʤ脽ěĂ凗蓏Ŋ蛊ĉy緅縕>Ž healthCheckNodePort: -1095807277 + ipFamily: ³-Ǐ忄*齧獚敆ȎțêɘIJ斬 loadBalancerIP: "25" loadBalancerSourceRanges: - "26"