Repository: envoyproxy/gateway

Issue:
worth to add a new DestinationAddressType type for UDS
should ideally be `UDS`
looks like this doesnt impact the final translation ?

_Originally posted by @arkodg in https://github.com/envoyproxy/gateway/pull/6370#discussion_r2167098154_
            

Discussion:
@github-actions: This issue has been automatically marked as stale because it has not had activity in the last 30 days.

Solution patch:
diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go
index 35b114b98..031764753 100644
--- a/internal/gatewayapi/route.go
+++ b/internal/gatewayapi/route.go
@@ -2003,7 +2003,7 @@ func (t *Translator) processBackendDestinationSetting(
 			addrTypeMap[ir.FQDN]++
 			irde = ir.NewDestEndpoint(bep.Hostname, bep.FQDN.Hostname, uint32(bep.FQDN.Port), false, bep.Zone)
 		case bep.Unix != nil:
-			addrTypeMap[ir.IP]++
+			addrTypeMap[ir.UDS]++
 			irde = &ir.DestinationEndpoint{
 				Path: ptr.To(bep.Unix.Path),
 				Zone: bep.Zone,
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index b7514a535..cc55f0de9 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -1685,6 +1685,7 @@ const (
 	IP    DestinationAddressType = "IP"
 	FQDN  DestinationAddressType = "FQDN"
 	MIXED DestinationAddressType = "Mixed"
+	UDS   DestinationAddressType = "UDS"
 )
 
 // DestinationEndpoint holds the endpoint details associated with the destination
diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go
index cd486b36c..dbf310280 100644
--- a/internal/provider/kubernetes/controller.go
+++ b/internal/provider/kubernetes/controller.go
@@ -1380,7 +1380,8 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g
 	mergedGateways := false
 	if r.mergeGateways.Has(managedGC.Name) {
 		mergedGateways = true
-		r.processServiceCluster(managedGC.Name, resourceMap)
+		// processGatewayClassParamsRef has been called for this gatewayclass, its EnvoyProxy should exist in resourceTree
+		r.processServiceClusterForGatewayClass(resourceTree.EnvoyProxyForGatewayClass, managedGC, resourceMap)
 	}
 
 	for _, gtw := range gatewayList.Items {
@@ -1422,10 +1423,6 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g
 
 		gtwNamespacedName := utils.NamespacedName(&gtw).String()
 
-		if !mergedGateways {
-			r.processServiceCluster(gtwNamespacedName, resourceMap)
-		}
-
 		// Route Processing
 
 		if r.tlsRouteCRDExists {
@@ -1478,6 +1475,15 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g
 			r.log.Error(err, "failed to process infrastructure.parametersRef for gateway", "namespace", gtw.Namespace, "name", gtw.Name)
 		}
 
+		if !mergedGateways {
+			var ep *egv1a1.EnvoyProxy = nil
+			if gtw.Spec.Infrastructure != nil && gtw.Spec.Infrastructure.ParametersRef != nil {
+				// processGatewayParamsRef has been called for this gateway, its EnvoyProxy should exist in resourceTree
+				ep = resourceTree.GetEnvoyProxy(gtw.Namespace, gtw.Spec.Infrastructure.ParametersRef.Name)
+			}
+			r.processServiceClusterForGateway(ep, &gtw, resourceMap)
+		}
+
 		if !resourceMap.allAssociatedGateways.Has(gtwNamespacedName) {
 			resourceMap.allAssociatedGateways.Insert(gtwNamespacedName)
 			resourceTree.Gateways = append(resourceTree.Gateways, &gtw)
@@ -1487,16 +1493,55 @@ func (r *gatewayAPIReconciler) processGateways(ctx context.Context, managedGC *g
 	return nil
 }
 
-func (r *gatewayAPIReconciler) processServiceCluster(resourceName string, resourceMap *resourceMappings) {
+// Called on a GatewayClass when merged gateways mode is enabled for it.
+func (r *gatewayAPIReconciler) processServiceClusterForGatewayClass(ep *egv1a1.EnvoyProxy, gatewayClass *gwapiv1.GatewayClass, resourceMap *resourceMappings) {
 	// Skip processing if topology injector is disabled
 	if r.envoyGateway != nil && r.envoyGateway.TopologyInjectorDisabled() {
 		return
 	}
 
-	proxySvcName := proxy.ExpectedResourceHashedName(resourceName)
+	proxySvcName, proxySvcNamespace := proxy.ExpectedResourceHashedName(gatewayClass.Name), r.namespace
+
+	// Check if the service name was specified in EnvoyProxy
+	if ep != nil {
+		provider := ep.GetEnvoyProxyProvider()
+		if provider.Kubernetes != nil && provider.Kubernetes.EnvoyService != nil && provider.Kubernetes.EnvoyService.Name != nil {
+			proxySvcName = *provider.Kubernetes.EnvoyService.Name
+		}
+	}
+
+	resourceMap.allAssociatedBackendRefs.Insert(gwapiv1.BackendObjectReference{
+		Kind:      ptr.To(gwapiv1.Kind("Service")),
+		Namespace: gatewayapi.NamespacePtr(proxySvcNamespace),
+		Name:      gwapiv1.ObjectName(proxySvcName),
+	})
+}
+
+// Called on a Gateway when merged gateways mode is not enabled for its parent GatewayClass.
+func (r *gatewayAPIReconciler) processServiceClusterForGateway(ep *egv1a1.EnvoyProxy, gateway *gwapiv1.Gateway, resourceMap *resourceMappings) {
+	// Skip processing if topology injector is disabled
+	if r.envoyGateway != nil && r.envoyGateway.TopologyInjectorDisabled() {
+		return
+	}
+
+	proxySvcName, proxySvcNamespace := proxy.ExpectedResourceHashedName(utils.NamespacedName(gateway).String()), r.namespace
+	// Check if gateway namespaced mode is used. If it is, the service's name is the same as
+	// the gateway's and it lives in the gateway's namespace not the controller's.
+	if r.gatewayNamespaceMode {
+		proxySvcName, proxySvcNamespace = gateway.Name, gateway.Namespace
+	}
+
+	// Check if the service name was specified in EnvoyProxy
+	if ep != nil {
+		provider := ep.GetEnvoyProxyProvider()
+		if provider.Kubernetes != nil && provider.Kubernetes.EnvoyService != nil && provider.Kubernetes.EnvoyService.Name != nil {
+			proxySvcName = *provider.Kubernetes.EnvoyService.Name
+		}
+	}
+
 	resourceMap.allAssociatedBackendRefs.Insert(gwapiv1.BackendObjectReference{
 		Kind:      ptr.To(gwapiv1.Kind("Service")),
-		Namespace: gatewayapi.NamespacePtr(r.namespace),
+		Namespace: gatewayapi.NamespacePtr(proxySvcNamespace),
 		Name:      gwapiv1.ObjectName(proxySvcName),
 	})
 }



Test patch:
diff --git a/internal/gatewayapi/testdata/accesslog-als-backend.out.yaml b/internal/gatewayapi/testdata/accesslog-als-backend.out.yaml
index 0ecd9d602..36d3e30cd 100644
--- a/internal/gatewayapi/testdata/accesslog-als-backend.out.yaml
+++ b/internal/gatewayapi/testdata/accesslog-als-backend.out.yaml
@@ -163,7 +163,7 @@ xdsIR:
             namespace: envoy-gateway-system
           name: accesslog_otel_0_0
           settings:
-          - addressType: IP
+          - addressType: UDS
             endpoints:
             - host: ""
               path: /var/run/backend.sock
diff --git a/internal/gatewayapi/testdata/envoyproxy-tracing-backend-uds.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tracing-backend-uds.out.yaml
index ab36d85fc..81cef801a 100644
--- a/internal/gatewayapi/testdata/envoyproxy-tracing-backend-uds.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-tracing-backend-uds.out.yaml
@@ -223,7 +223,7 @@ xdsIR:
           namespace: envoy-gateway-system
         name: tracing
         settings:
-        - addressType: IP
+        - addressType: UDS
           endpoints:
           - host: ""
             path: /var/run/envoy-uds/dsd.socket
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
index 46ef87404..e1294c259 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
@@ -619,7 +619,7 @@ xdsIR:
                   namespace: default
                 name: securitypolicy/default/policy-for-http-route-3-http-backendref/extauth/0
                 settings:
-                - addressType: IP
+                - addressType: UDS
                   endpoints:
                   - host: ""
                     path: /var/run/uds.sock
diff --git a/internal/provider/kubernetes/controller_test.go b/internal/provider/kubernetes/controller_test.go
index 523940bb4..bb23b27be 100644
--- a/internal/provider/kubernetes/controller_test.go
+++ b/internal/provider/kubernetes/controller_test.go
@@ -30,6 +30,7 @@ import (
 	"github.com/envoyproxy/gateway/internal/envoygateway/config"
 	"github.com/envoyproxy/gateway/internal/gatewayapi"
 	"github.com/envoyproxy/gateway/internal/gatewayapi/resource"
+	"github.com/envoyproxy/gateway/internal/infrastructure/kubernetes/proxy"
 	"github.com/envoyproxy/gateway/internal/logging"
 	"github.com/envoyproxy/gateway/internal/provider/kubernetes/test"
 	"github.com/envoyproxy/gateway/internal/utils"
@@ -1247,6 +1248,191 @@ func TestProcessSecurityPolicyObjectRefs(t *testing.T) {
 	}
 }
 
+func TestProcessServiceClusterForGatewayClass(t *testing.T) {
+	testCases := []struct {
+		name            string
+		gatewayClass    *gwapiv1.GatewayClass
+		envoyProxy      *egv1a1.EnvoyProxy
+		expectedSvcName string
+	}{
+		{
+			name: "when merged gateways and no hardcoded svc name is used",
+			gatewayClass: &gwapiv1.GatewayClass{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "merged-gc",
+				},
+			},
+			envoyProxy:      nil,
+			expectedSvcName: proxy.ExpectedResourceHashedName("merged-gc"),
+		},
+		{
+			name: "when merged gateways and a hardcoded svc name is used",
+			gatewayClass: &gwapiv1.GatewayClass{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "merged-gc",
+				},
+			},
+			envoyProxy: &egv1a1.EnvoyProxy{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "merged-gc",
+				},
+				Spec: egv1a1.EnvoyProxySpec{
+					Provider: &egv1a1.EnvoyProxyProvider{
+						Type: egv1a1.ProviderTypeKubernetes,
+						Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{
+							EnvoyService: &egv1a1.KubernetesServiceSpec{
+								Name: ptr.To("merged-gc-svc"),
+							},
+						},
+					},
+				},
+			},
+			expectedSvcName: "merged-gc-svc",
+		},
+	}
+
+	for i := range testCases {
+		tc := testCases[i]
+		// Run the test cases.
+		t.Run(tc.name, func(t *testing.T) {
+			logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
+			resourceMap := newResourceMapping()
+
+			r := newGatewayAPIReconciler(logger)
+			r.namespace = "envoy-gateway-system"
+
+			r.processServiceClusterForGatewayClass(tc.envoyProxy, tc.gatewayClass, resourceMap)
+
+			require.Contains(t, resourceMap.allAssociatedBackendRefs, gwapiv1.BackendObjectReference{
+				Kind:      ptr.To(gwapiv1.Kind("Service")),
+				Namespace: gatewayapi.NamespacePtr(r.namespace),
+				Name:      gwapiv1.ObjectName(tc.expectedSvcName),
+			})
+		})
+	}
+}
+
+func TestProcessServiceClusterForGateway(t *testing.T) {
+	testCases := []struct {
+		name                  string
+		gateway               *gwapiv1.Gateway
+		envoyProxy            *egv1a1.EnvoyProxy
+		gatewayNamespacedMode bool
+		expectedSvcName       string
+		expectedSvcNamespace  string
+	}{
+		{
+			name: "no gateway namespaced mode with no hardcoded service name",
+			gateway: &gwapiv1.Gateway{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "my-gateway",
+					Namespace: "app-namespace",
+				},
+			},
+			envoyProxy:            nil,
+			gatewayNamespacedMode: false,
+			expectedSvcName:       "",
+			expectedSvcNamespace:  "",
+		},
+		{
+			name: "no gateway namespaced mode with hardcoded service name",
+			gateway: &gwapiv1.Gateway{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "my-gateway",
+					Namespace: "app-namespace",
+				},
+			},
+			envoyProxy: &egv1a1.EnvoyProxy{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "my-gateway",
+				},
+				Spec: egv1a1.EnvoyProxySpec{
+					Provider: &egv1a1.EnvoyProxyProvider{
+						Type: egv1a1.ProviderTypeKubernetes,
+						Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{
+							EnvoyService: &egv1a1.KubernetesServiceSpec{
+								Name: ptr.To("my-gateway-svc"),
+							},
+						},
+					},
+				},
+			},
+			gatewayNamespacedMode: false,
+			expectedSvcName:       "my-gateway-svc",
+			expectedSvcNamespace:  "",
+		},
+		{
+			name: "gateway namespaced mode with no hardcoded service name",
+			gateway: &gwapiv1.Gateway{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "my-gateway",
+					Namespace: "app-namespace",
+				},
+			},
+			envoyProxy:            nil,
+			gatewayNamespacedMode: true,
+			expectedSvcName:       "my-gateway",
+			expectedSvcNamespace:  "app-namespace",
+		},
+		{
+			name: "gateway namespaced mode with hardcoded service name",
+			gateway: &gwapiv1.Gateway{
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      "my-gateway",
+					Namespace: "app-namespace",
+				},
+			},
+			envoyProxy: &egv1a1.EnvoyProxy{
+				ObjectMeta: metav1.ObjectMeta{
+					Name: "my-gateway",
+				},
+				Spec: egv1a1.EnvoyProxySpec{
+					Provider: &egv1a1.EnvoyProxyProvider{
+						Type: egv1a1.ProviderTypeKubernetes,
+						Kubernetes: &egv1a1.EnvoyProxyKubernetesProvider{
+							EnvoyService: &egv1a1.KubernetesServiceSpec{
+								Name: ptr.To("my-gateway-svc"),
+							},
+						},
+					},
+				},
+			},
+			gatewayNamespacedMode: true,
+			expectedSvcName:       "my-gateway-svc",
+			expectedSvcNamespace:  "app-namespace",
+		},
+	}
+
+	for i := range testCases {
+		tc := testCases[i]
+		// Run the test cases.
+		t.Run(tc.name, func(t *testing.T) {
+			logger := logging.DefaultLogger(os.Stdout, egv1a1.LogLevelInfo)
+			resourceMap := newResourceMapping()
+
+			r := newGatewayAPIReconciler(logger)
+			r.namespace = "envoy-gateway-system"
+			r.gatewayNamespaceMode = tc.gatewayNamespacedMode
+
+			if tc.expectedSvcNamespace == "" {
+				tc.expectedSvcNamespace = r.namespace
+			}
+
+			if tc.expectedSvcName == "" {
+				tc.expectedSvcName = proxy.ExpectedResourceHashedName(utils.NamespacedName(tc.gateway).String())
+			}
+
+			r.processServiceClusterForGateway(tc.envoyProxy, tc.gateway, resourceMap)
+
+			require.Contains(t, resourceMap.allAssociatedBackendRefs, gwapiv1.BackendObjectReference{
+				Kind:      ptr.To(gwapiv1.Kind("Service")),
+				Namespace: gatewayapi.NamespacePtr(tc.expectedSvcNamespace),
+				Name:      gwapiv1.ObjectName(tc.expectedSvcName),
+			})
+		})
+	}
+}
+
 func newGatewayAPIReconciler(logger logging.Logger) *gatewayAPIReconciler {
 	return &gatewayAPIReconciler{
 		log:              logger,
diff --git a/internal/xds/translator/testdata/in/xds-ir/tracing-datadog-uds.yaml b/internal/xds/translator/testdata/in/xds-ir/tracing-datadog-uds.yaml
index 694c99fd2..5281717c8 100644
--- a/internal/xds/translator/testdata/in/xds-ir/tracing-datadog-uds.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/tracing-datadog-uds.yaml
@@ -21,7 +21,7 @@ tracing:
   destination:
     name: "tracing-0"
     settings:
-      - addressType: IP
+      - addressType: UDS
         endpoints:
           - host: ""
             path: /var/run/envoy-uds/dsd.socket
diff --git a/test/e2e/testdata/zone-aware-routing-btp-enabled.yaml b/test/e2e/testdata/zone-aware-routing-btp-force-local-zone.yaml
similarity index 81%
rename from test/e2e/testdata/zone-aware-routing-btp-enabled.yaml
rename to test/e2e/testdata/zone-aware-routing-btp-force-local-zone.yaml
index 28536127b..eadc25c0f 100644
--- a/test/e2e/testdata/zone-aware-routing-btp-enabled.yaml
+++ b/test/e2e/testdata/zone-aware-routing-btp-force-local-zone.yaml
@@ -1,7 +1,7 @@
 apiVersion: v1
 kind: Service
 metadata:
-  name: btp-zone-aware
+  name: btp-force-local-zone
   namespace: gateway-conformance-infra
 spec:
   selector:
@@ -15,7 +15,7 @@ spec:
 apiVersion: gateway.networking.k8s.io/v1
 kind: HTTPRoute
 metadata:
-  name: btp-zone-aware
+  name: btp-force-local-zone
   namespace: gateway-conformance-infra
 spec:
   parentRefs:
@@ -24,22 +24,22 @@ spec:
     - matches:
         - path:
             type: PathPrefix
-            value: /btp-zone-aware
+            value: /btp-force-local-zone
       backendRefs:
-        - name: btp-zone-aware
+        - name: btp-force-local-zone
           port: 8080
           weight: 1
 ---
 apiVersion: gateway.envoyproxy.io/v1alpha1
 kind: BackendTrafficPolicy
 metadata:
-  name: btp-zone-aware
+  name: btp-force-local-zone
   namespace: gateway-conformance-infra
 spec:
   targetRefs:
     - group: gateway.networking.k8s.io
       kind: HTTPRoute
-      name: btp-zone-aware
+      name: btp-force-local-zone
   loadBalancer:
     type: RoundRobin
     zoneAware:
diff --git a/test/e2e/testdata/zone-aware-routing-btp-no-force-local-zone.yaml b/test/e2e/testdata/zone-aware-routing-btp-no-force-local-zone.yaml
new file mode 100644
index 000000000..740896187
--- /dev/null
+++ b/test/e2e/testdata/zone-aware-routing-btp-no-force-local-zone.yaml
@@ -0,0 +1,47 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: btp-no-force-local-zone
+  namespace: gateway-conformance-infra
+spec:
+  selector:
+    app: zone-aware-backend
+  ports:
+    - protocol: TCP
+      port: 8080
+      name: http11
+      targetPort: 3000
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: btp-no-force-local-zone
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: same-namespace
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /btp-no-force-local-zone
+      backendRefs:
+        - name: btp-no-force-local-zone
+          port: 8080
+          weight: 1
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: btp-no-force-local-zone
+  namespace: gateway-conformance-infra
+spec:
+  targetRefs:
+    - group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: btp-no-force-local-zone
+  loadBalancer:
+    type: RoundRobin
+    zoneAware:
+      preferLocal:
+        minEndpointsThreshold: 1
diff --git a/test/e2e/testdata/zone-aware-routing-gateways.yaml b/test/e2e/testdata/zone-aware-routing-gateways.yaml
new file mode 100644
index 000000000..90d678169
--- /dev/null
+++ b/test/e2e/testdata/zone-aware-routing-gateways.yaml
@@ -0,0 +1,91 @@
+# zone-aware-routing-gtw should be similar to `same-namespace` gateway, only difference
+# is having a hard-coded service name in the EnvoyProxy attached, to test zone-aware-routing
+# in that case when no ForceLocal is specified.
+apiVersion: gateway.networking.k8s.io/v1
+kind: Gateway
+metadata:
+  name: zone-aware-routing-gtw
+  namespace: gateway-conformance-infra
+spec:
+  gatewayClassName: "{GATEWAY_CLASS_NAME}"
+  listeners:
+    - name: http
+      port: 80
+      protocol: HTTP
+      allowedRoutes:
+        namespaces:
+          from: Same
+    - name: tls
+      protocol: TLS
+      port: 443
+      tls:
+        mode: Passthrough
+      allowedRoutes:
+        namespaces:
+          from: Same
+  infrastructure:
+    parametersRef:
+      group: gateway.envoyproxy.io
+      kind: EnvoyProxy
+      name: zone-aware-routing
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: EnvoyProxy
+metadata:
+  name: zone-aware-routing
+  namespace: gateway-conformance-infra
+spec:
+  ipFamily: IPv4
+  provider:
+    type: Kubernetes
+    kubernetes:
+      envoyService:
+        name: zone-aware-routing-gtw
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: btp-no-force-local-zone-hardcoded-svc-name
+  namespace: gateway-conformance-infra
+spec:
+  selector:
+    app: zone-aware-backend
+  ports:
+    - protocol: TCP
+      port: 8080
+      name: http11
+      targetPort: 3000
+---
+apiVersion: gateway.networking.k8s.io/v1
+kind: HTTPRoute
+metadata:
+  name: btp-no-force-local-zone-hardcoded-svc-name
+  namespace: gateway-conformance-infra
+spec:
+  parentRefs:
+    - name: zone-aware-routing-gtw
+  rules:
+    - matches:
+        - path:
+            type: PathPrefix
+            value: /btp-no-force-local-zone-hardcoded-svc-name
+      backendRefs:
+        - name: btp-no-force-local-zone-hardcoded-svc-name
+          port: 8080
+          weight: 1
+---
+apiVersion: gateway.envoyproxy.io/v1alpha1
+kind: BackendTrafficPolicy
+metadata:
+  name: btp-no-force-local-zone-hardcoded-svc-name
+  namespace: gateway-conformance-infra
+spec:
+  targetRefs:
+    - group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: btp-no-force-local-zone-hardcoded-svc-name
+  loadBalancer:
+    type: RoundRobin
+    zoneAware:
+      preferLocal:
+        minEndpointsThreshold: 1
diff --git a/test/e2e/tests/weighted_backend.go b/test/e2e/tests/weighted_backend.go
index 154c6f5fb..51fc0d1cb 100644
--- a/test/e2e/tests/weighted_backend.go
+++ b/test/e2e/tests/weighted_backend.go
@@ -39,7 +39,7 @@ var WeightedBackendTest = suite.ConformanceTest{
 				"infra-backend-v1": sendRequests * .5,
 				"infra-backend-v2": sendRequests * .5,
 			}
-			runWeightedBackendTest(t, suite, "weight-equal-http-route", "/same-weight", "infra-backend", expected)
+			runWeightedBackendTest(t, suite, nil, "weight-equal-http-route", "/same-weight", "infra-backend", expected)
 		})
 		t.Run("BlueGreen", func(t *testing.T) {
 			// The received request is approximately 9:1
@@ -47,7 +47,7 @@ var WeightedBackendTest = suite.ConformanceTest{
 				"infra-backend-v1": sendRequests * .9,
 				"infra-backend-v2": sendRequests * .1,
 			}
-			runWeightedBackendTest(t, suite, "weight-bluegreen-http-route", "/blue-green", "infra-backend", expected)
+			runWeightedBackendTest(t, suite, nil, "weight-bluegreen-http-route", "/blue-green", "infra-backend", expected)
 		})
 		t.Run("CompleteRollout", func(t *testing.T) {
 			// All the requests should be proxied to v1
@@ -55,16 +55,20 @@ var WeightedBackendTest = suite.ConformanceTest{
 				"infra-backend-v1": sendRequests * 1,
 				"infra-backend-v2": sendRequests * 0,
 			}
-			runWeightedBackendTest(t, suite, "weight-complete-rollout-http-route", "/complete-rollout", "infra-backend", expected)
+			runWeightedBackendTest(t, suite, nil, "weight-complete-rollout-http-route", "/complete-rollout", "infra-backend", expected)
 		})
 	},
 }
 
-func runWeightedBackendTest(t *testing.T, suite *suite.ConformanceTestSuite, routeName, path, backendName string, expectedOutput map[string]int) {
+func runWeightedBackendTest(t *testing.T, suite *suite.ConformanceTestSuite, gateway *types.NamespacedName, routeName, path, backendName string, expectedOutput map[string]int) {
 	weightEqualRoute := types.NamespacedName{Name: routeName, Namespace: ConformanceInfraNamespace}
-	gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig,
-		suite.ControllerName,
-		kubernetes.NewGatewayRef(SameNamespaceGateway), weightEqualRoute)
+
+	gatewayRef := kubernetes.NewGatewayRef(SameNamespaceGateway)
+	if gateway != nil {
+		gatewayRef = kubernetes.NewGatewayRef(*gateway)
+	}
+
+	gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, gatewayRef, weightEqualRoute)
 
 	// Make sure all test resources are ready
 	kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ConformanceInfraNamespace})
diff --git a/test/e2e/tests/zone_aware_routing.go b/test/e2e/tests/zone_aware_routing.go
index 64699c7f5..123447040 100644
--- a/test/e2e/tests/zone_aware_routing.go
+++ b/test/e2e/tests/zone_aware_routing.go
@@ -8,6 +8,7 @@
 package tests
 
 import (
+	"math"
 	"testing"
 
 	"k8s.io/apimachinery/pkg/types"
@@ -28,8 +29,10 @@ var ZoneAwareRoutingTest = suite.ConformanceTest{
 	Description: "Test Zone Aware Routing is working",
 	Manifests: []string{
 		"testdata/zone-aware-routing-backendref-enabled.yaml",
-		"testdata/zone-aware-routing-btp-enabled.yaml",
+		"testdata/zone-aware-routing-btp-force-local-zone.yaml",
+		"testdata/zone-aware-routing-btp-no-force-local-zone.yaml",
 		"testdata/zone-aware-routing-deployments.yaml",
+		"testdata/zone-aware-routing-gateways.yaml",
 	},
 	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
 		t.Run("topology aware routing - only local zone should get requests", func(t *testing.T) {
@@ -39,12 +42,12 @@ var ZoneAwareRoutingTest = suite.ConformanceTest{
 				"zone-aware-backend-local":    sendRequests,
 				"zone-aware-backend-nonlocal": 0,
 			}
-			runWeightedBackendTest(t, suite, "topology-aware-routing", "/topology-aware-routing", "zone-aware-backend", expected)
+			runWeightedBackendTest(t, suite, nil, "topology-aware-routing", "/topology-aware-routing", "zone-aware-backend", expected)
 		})
-		t.Run("BackendTrafficPolicy - only local zone should get requests", func(t *testing.T) {
+		t.Run("BackendTrafficPolicy - ForceLocalZone - only local zone should get requests", func(t *testing.T) {
 			BackendTrafficPolicyMustBeAccepted(t,
 				suite.Client,
-				types.NamespacedName{Name: "btp-zone-aware", Namespace: "gateway-conformance-infra"},
+				types.NamespacedName{Name: "btp-force-local-zone", Namespace: "gateway-conformance-infra"},
 				suite.ControllerName,
 				gwapiv1a2.ParentReference{
 					Group:     gatewayapi.GroupPtr(gwapiv1.GroupName),
@@ -60,7 +63,53 @@ var ZoneAwareRoutingTest = suite.ConformanceTest{
 				"zone-aware-backend-local":    sendRequests,
 				"zone-aware-backend-nonlocal": 0,
 			}
-			runWeightedBackendTest(t, suite, "btp-zone-aware", "/btp-zone-aware", "zone-aware-backend", expected)
+			runWeightedBackendTest(t, suite, nil, "btp-force-local-zone", "/btp-force-local-zone", "zone-aware-backend", expected)
+		})
+		t.Run("BackendTrafficPolicy - No ForceLocalZone - local zone should get around 75% of requests", func(t *testing.T) {
+			BackendTrafficPolicyMustBeAccepted(t,
+				suite.Client,
+				types.NamespacedName{Name: "btp-no-force-local-zone", Namespace: "gateway-conformance-infra"},
+				suite.ControllerName,
+				gwapiv1a2.ParentReference{
+					Group:     gatewayapi.GroupPtr(gwapiv1.GroupName),
+					Kind:      gatewayapi.KindPtr(resource.KindGateway),
+					Namespace: gatewayapi.NamespacePtr("gateway-conformance-infra"),
+					Name:      gwapiv1.ObjectName("same-namespace"),
+				},
+			)
+
+			// Pods from the backend-local deployment have affinity for the Envoy Proxy pods.
+			// ForceLocal is not used, and overall we have 4 backend pods, 3 local and 1 non-local.
+			// Distribution of upstream is 75% local, 25% non-local. Distribution of envoy is 100% local.
+			// Expect local upstream to get around 75% of traffic.
+			expected := map[string]int{
+				"zone-aware-backend-local":    int(math.Round(sendRequests * .75)),
+				"zone-aware-backend-nonlocal": int(math.Round(sendRequests * .25)),
+			}
+			runWeightedBackendTest(t, suite, nil, "btp-no-force-local-zone", "/btp-no-force-local-zone", "zone-aware-backend", expected)
+		})
+		t.Run("BackendTrafficPolicy - No ForceLocalZone - Hardcoded service name in EnvoyProxy - local zone should get around 75% of requests", func(t *testing.T) {
+			BackendTrafficPolicyMustBeAccepted(t,
+				suite.Client,
+				types.NamespacedName{Name: "btp-no-force-local-zone-hardcoded-svc-name", Namespace: "gateway-conformance-infra"},
+				suite.ControllerName,
+				gwapiv1a2.ParentReference{
+					Group:     gatewayapi.GroupPtr(gwapiv1.GroupName),
+					Kind:      gatewayapi.KindPtr(resource.KindGateway),
+					Namespace: gatewayapi.NamespacePtr("gateway-conformance-infra"),
+					Name:      gwapiv1.ObjectName("zone-aware-routing-gtw"),
+				},
+			)
+
+			// Pods from the backend-local deployment have affinity for the Envoy Proxy pods.
+			// ForceLocal is not used, and overall we have 4 backend pods, 3 local and 1 non-local.
+			// Distribution of upstream is 75% local, 25% non-local. Distribution of envoy is 100% local.
+			// Expect local upstream to get around 75% of traffic.
+			expected := map[string]int{
+				"zone-aware-backend-local":    int(math.Round(sendRequests * .75)),
+				"zone-aware-backend-nonlocal": int(math.Round(sendRequests * .25)),
+			}
+			runWeightedBackendTest(t, suite, &types.NamespacedName{Name: "zone-aware-routing-gtw", Namespace: "gateway-conformance-infra"}, "btp-no-force-local-zone-hardcoded-svc-name", "/btp-no-force-local-zone-hardcoded-svc-name", "zone-aware-backend", expected)
 		})
 	},
 }