Repository: envoyproxy/gateway
Pull request #3885 (2024-07-17 14:29:11)

accesslog: fix different CelMatches on AccessLog
found out this when debuging https://github.com/envoyproxy/gateway/pull/3884

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/3885?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
Attention: Patch coverage is `97.22222%` with `1 line` in your changes missing coverage. Please review.
> Project coverage is 69.26%. Comparing base [(`4ebd397`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/4ebd39718e49f54bbea1aa3e162a46d3c56a5ec6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`0a8198e`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/0a8198ea03503aa5a02356956c274bf89bb13cd1?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

| [Files](https://app.codecov.io/gh/envoyproxy/gateway/pull/3885?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) | Patch % | Lines |
|---|---|---|
| [internal/xds/translator/accesslog.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/3885?src=pr&el=tree&filepath=internal%2Fxds%2Ftranslator%2Faccesslog.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwveGRzL3RyYW5zbGF0b3IvYWNjZXNzbG9nLmdv) | 93.33% | [1 Missing :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/3885?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #3885      +/-   ##
==========================================
- Coverage   69.33%   69.26%   -0.07%     
==========================================
  Files         176      176              
  Lines       21746    21751       +5     
==========================================
- Hits        15077    15066      -11     
- Misses       5580     5594      +14     
- Partials     1089     1091       +2     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/3885?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).


Patch:
diff --git a/api/v1alpha1/accesslogging_types.go b/api/v1alpha1/accesslogging_types.go
index 765fa4de7..242725644 100644
--- a/api/v1alpha1/accesslogging_types.go
+++ b/api/v1alpha1/accesslogging_types.go
@@ -20,7 +20,7 @@ type ProxyAccessLogSetting struct {
 	// Format defines the format of accesslog.
 	// This will be ignored if sink type is ALS.
 	// +optional
-	Format *ProxyAccessLogFormat `json:"format"`
+	Format *ProxyAccessLogFormat `json:"format,omitempty"`
 	// Matches defines the match conditions for accesslog in CEL expression.
 	// An accesslog will be emitted only when one or more match conditions are evaluated to true.
 	// Invalid [CEL](https://www.envoyproxy.io/docs/envoy/latest/xds/type/v3/cel.proto.html#common-expression-language-cel-proto) expressions will be ignored.
diff --git a/internal/gatewayapi/envoyextensionpolicy.go b/internal/gatewayapi/envoyextensionpolicy.go
index 4206e9a69..081e8f641 100644
--- a/internal/gatewayapi/envoyextensionpolicy.go
+++ b/internal/gatewayapi/envoyextensionpolicy.go
@@ -351,8 +351,10 @@ func (t *Translator) translateEnvoyExtensionPolicyForRoute(
 			if irListener != nil {
 				for _, r := range irListener.Routes {
 					if strings.HasPrefix(r.Name, prefix) {
-						r.ExtProcs = extProcs
-						r.Wasms = wasms
+						r.EnvoyExtensions = &ir.EnvoyExtensionFeatures{
+							ExtProcs: extProcs,
+							Wasms:    wasms,
+						}
 					}
 				}
 			}
@@ -405,16 +407,13 @@ func (t *Translator) translateEnvoyExtensionPolicyForGateway(
 		// targeting a lesser specific scope(Gateway).
 		for _, r := range http.Routes {
 			// if already set - there's a route level policy, so skip
-			if r.ExtProcs != nil ||
-				r.Wasms != nil {
+			if r.EnvoyExtensions != nil {
 				continue
 			}
 
-			if r.ExtProcs == nil {
-				r.ExtProcs = extProcs
-			}
-			if r.Wasms == nil {
-				r.Wasms = wasms
+			r.EnvoyExtensions = &ir.EnvoyExtensionFeatures{
+				ExtProcs: extProcs,
+				Wasms:    wasms,
 			}
 		}
 	}
diff --git a/internal/gatewayapi/listener.go b/internal/gatewayapi/listener.go
index 4eac0e11c..adbd302b9 100644
--- a/internal/gatewayapi/listener.go
+++ b/internal/gatewayapi/listener.go
@@ -257,6 +257,21 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources *
 			}
 		}
 
+		var (
+			validExprs []string
+			errs       []error
+		)
+		for _, expr := range accessLog.Matches {
+			if !validCELExpression(expr) {
+				errs = append(errs, fmt.Errorf("invalid CEL expression: %s", expr))
+				continue
+			}
+			validExprs = append(validExprs, expr)
+		}
+		if len(errs) > 0 {
+			return nil, utilerrors.NewAggregate(errs)
+		}
+
 		for j, sink := range accessLog.Sinks {
 			switch sink.Type {
 			case egv1a1.ProxyAccessLogSinkTypeFile:
@@ -267,8 +282,9 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources *
 				switch format.Type {
 				case egv1a1.ProxyAccessLogFormatTypeText:
 					al := &ir.TextAccessLog{
-						Format: format.Text,
-						Path:   sink.File.Path,
+						Format:     format.Text,
+						Path:       sink.File.Path,
+						CELMatches: validExprs,
 					}
 					irAccessLog.Text = append(irAccessLog.Text, al)
 				case egv1a1.ProxyAccessLogFormatTypeJSON:
@@ -278,8 +294,9 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources *
 					}
 
 					al := &ir.JSONAccessLog{
-						JSON: format.JSON,
-						Path: sink.File.Path,
+						JSON:       format.JSON,
+						Path:       sink.File.Path,
+						CELMatches: validExprs,
 					}
 					irAccessLog.JSON = append(irAccessLog.JSON, al)
 				}
@@ -307,7 +324,8 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources *
 						Name:     fmt.Sprintf("accesslog_als_%d_%d", i, j), // TODO: rename this, so that we can share backend with tracing?
 						Settings: ds,
 					},
-					Type: sink.ALS.Type,
+					Type:       sink.ALS.Type,
+					CELMatches: validExprs,
 				}
 
 				if al.Type == egv1a1.ALSEnvoyProxyAccessLogTypeHTTP && sink.ALS.HTTP != nil {
@@ -334,7 +352,8 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources *
 
 				// TODO: remove support for Host/Port in v1.2
 				al := &ir.OpenTelemetryAccessLog{
-					Resources: sink.OpenTelemetry.Resources,
+					CELMatches: validExprs,
+					Resources:  sink.OpenTelemetry.Resources,
 				}
 
 				// TODO: how to get authority from the backendRefs?
@@ -368,22 +387,6 @@ func (t *Translator) processAccessLog(envoyproxy *egv1a1.EnvoyProxy, resources *
 				irAccessLog.OpenTelemetry = append(irAccessLog.OpenTelemetry, al)
 			}
 		}
-
-		var (
-			validExprs []string
-			errs       []error
-		)
-		for _, expr := range accessLog.Matches {
-			if !validCELExpression(expr) {
-				errs = append(errs, fmt.Errorf("invalid CEL expression: %s", expr))
-				continue
-			}
-			validExprs = append(validExprs, expr)
-		}
-		if len(errs) > 0 {
-			return nil, utilerrors.NewAggregate(errs)
-		}
-		irAccessLog.CELMatches = validExprs
 	}
 
 	return irAccessLog, nil
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index 8dc95e783..86b83fb93 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -553,15 +553,12 @@ type HTTPRoute struct {
 	URLRewrite *URLRewrite `json:"urlRewrite,omitempty" yaml:"urlRewrite,omitempty"`
 	// ExtensionRefs holds unstructured resources that were introduced by an extension and used on the HTTPRoute as extensionRef filters
 	ExtensionRefs []*UnstructuredRef `json:"extensionRefs,omitempty" yaml:"extensionRefs,omitempty"`
-	// External Processing extensions
-	ExtProcs []ExtProc `json:"extProc,omitempty" yaml:"extProc,omitempty"`
-	// Wasm extensions
-	Wasms []Wasm `json:"wasm,omitempty" yaml:"wasm,omitempty"`
-
 	// Traffic holds the features associated with BackendTrafficPolicy
 	Traffic *TrafficFeatures `json:"traffic,omitempty" yaml:"traffic,omitempty"`
 	// Security holds the features associated with SecurityPolicy
 	Security *SecurityFeatures `json:"security,omitempty" yaml:"security,omitempty"`
+	// EnvoyExtension holds the features associated with EnvoyExtensionPolicy
+	EnvoyExtensions *EnvoyExtensionFeatures `json:"envoyExtensions,omitempty" yaml:"envoyExtensions,omitempty"`
 	// UseClientProtocol enables using the same protocol upstream that was used downstream
 	UseClientProtocol *bool `json:"useClientProtocol,omitempty" yaml:"useClientProtocol,omitempty"`
 	// Metadata is used to enrich envoy route metadata with user and provider-specific information
@@ -652,6 +649,15 @@ func (s *SecurityFeatures) Validate() error {
 	return errs
 }
 
+// EnvoyExtensionFeatures holds the information associated with the Envoy Extension Policy.
+// +k8s:deepcopy-gen=true
+type EnvoyExtensionFeatures struct {
+	// External Processing extensions
+	ExtProcs []ExtProc `json:"extProcs,omitempty" yaml:"extProcs,omitempty"`
+	// Wasm extensions
+	Wasms []Wasm `json:"wasms,omitempty" yaml:"wasms,omitempty"`
+}
+
 // UnstructuredRef holds unstructured data for an arbitrary k8s resource introduced by an extension
 // Envoy Gateway does not need to know about the resource types in order to store and pass the data for these objects
 // to an extension.
@@ -1603,7 +1609,6 @@ type RateLimitValue struct {
 // AccessLog holds the access logging configuration.
 // +k8s:deepcopy-gen=true
 type AccessLog struct {
-	CELMatches    []string                  `json:"celMatches,omitempty" yaml:"celMatches,omitempty"`
 	Text          []*TextAccessLog          `json:"text,omitempty" yaml:"text,omitempty"`
 	JSON          []*JSONAccessLog          `json:"json,omitempty" yaml:"json,omitempty"`
 	ALS           []*ALSAccessLog           `json:"als,omitempty" yaml:"als,omitempty"`
@@ -1613,20 +1618,23 @@ type AccessLog struct {
 // TextAccessLog holds the configuration for text access logging.
 // +k8s:deepcopy-gen=true
 type TextAccessLog struct {
-	Format *string `json:"format,omitempty" yaml:"format,omitempty"`
-	Path   string  `json:"path" yaml:"path"`
+	CELMatches []string `json:"celMatches,omitempty" yaml:"celMatches,omitempty"`
+	Format     *string  `json:"format,omitempty" yaml:"format,omitempty"`
+	Path       string   `json:"path" yaml:"path"`
 }
 
 // JSONAccessLog holds the configuration for JSON access logging.
 // +k8s:deepcopy-gen=true
 type JSONAccessLog struct {
-	JSON map[string]string `json:"json,omitempty" yaml:"json,omitempty"`
-	Path string            `json:"path" yaml:"path"`
+	CELMatches []string          `json:"celMatches,omitempty" yaml:"celMatches,omitempty"`
+	JSON       map[string]string `json:"json,omitempty" yaml:"json,omitempty"`
+	Path       string            `json:"path" yaml:"path"`
 }
 
 // ALSAccessLog holds the configuration for gRPC ALS access logging.
 // +k8s:deepcopy-gen=true
 type ALSAccessLog struct {
+	CELMatches  []string                          `json:"celMatches,omitempty" yaml:"celMatches,omitempty"`
 	LogName     string                            `json:"name" yaml:"name"`
 	Destination RouteDestination                  `json:"destination,omitempty" yaml:"destination,omitempty"`
 	Type        egv1a1.ALSEnvoyProxyAccessLogType `json:"type" yaml:"type"`
@@ -1646,6 +1654,7 @@ type ALSAccessLogHTTP struct {
 // OpenTelemetryAccessLog holds the configuration for OpenTelemetry access logging.
 // +k8s:deepcopy-gen=true
 type OpenTelemetryAccessLog struct {
+	CELMatches  []string          `json:"celMatches,omitempty" yaml:"celMatches,omitempty"`
 	Authority   string            `json:"authority,omitempty" yaml:"authority,omitempty"`
 	Text        *string           `json:"text,omitempty" yaml:"text,omitempty"`
 	Attributes  map[string]string `json:"attributes,omitempty" yaml:"attributes,omitempty"`
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index d76ea363c..0f523fb1e 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -19,6 +19,11 @@ import (
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ALSAccessLog) DeepCopyInto(out *ALSAccessLog) {
 	*out = *in
+	if in.CELMatches != nil {
+		in, out := &in.CELMatches, &out.CELMatches
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	in.Destination.DeepCopyInto(&out.Destination)
 	if in.Text != nil {
 		in, out := &in.Text, &out.Text
@@ -82,11 +87,6 @@ func (in *ALSAccessLogHTTP) DeepCopy() *ALSAccessLogHTTP {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *AccessLog) DeepCopyInto(out *AccessLog) {
 	*out = *in
-	if in.CELMatches != nil {
-		in, out := &in.CELMatches, &out.CELMatches
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
 	if in.Text != nil {
 		in, out := &in.Text, &out.Text
 		*out = make([]*TextAccessLog, len(*in))
@@ -683,6 +683,35 @@ func (in *DirectResponse) DeepCopy() *DirectResponse {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *EnvoyExtensionFeatures) DeepCopyInto(out *EnvoyExtensionFeatures) {
+	*out = *in
+	if in.ExtProcs != nil {
+		in, out := &in.ExtProcs, &out.ExtProcs
+		*out = make([]ExtProc, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Wasms != nil {
+		in, out := &in.Wasms, &out.Wasms
+		*out = make([]Wasm, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvoyExtensionFeatures.
+func (in *EnvoyExtensionFeatures) DeepCopy() *EnvoyExtensionFeatures {
+	if in == nil {
+		return nil
+	}
+	out := new(EnvoyExtensionFeatures)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *EnvoyPatchPolicy) DeepCopyInto(out *EnvoyPatchPolicy) {
 	*out = *in
@@ -1269,20 +1298,6 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
 			}
 		}
 	}
-	if in.ExtProcs != nil {
-		in, out := &in.ExtProcs, &out.ExtProcs
-		*out = make([]ExtProc, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-	if in.Wasms != nil {
-		in, out := &in.Wasms, &out.Wasms
-		*out = make([]Wasm, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
 	if in.Traffic != nil {
 		in, out := &in.Traffic, &out.Traffic
 		*out = new(TrafficFeatures)
@@ -1293,6 +1308,11 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
 		*out = new(SecurityFeatures)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.EnvoyExtensions != nil {
+		in, out := &in.EnvoyExtensions, &out.EnvoyExtensions
+		*out = new(EnvoyExtensionFeatures)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.UseClientProtocol != nil {
 		in, out := &in.UseClientProtocol, &out.UseClientProtocol
 		*out = new(bool)
@@ -1497,6 +1517,11 @@ func (in *InfraMetadata) DeepCopy() *InfraMetadata {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *JSONAccessLog) DeepCopyInto(out *JSONAccessLog) {
 	*out = *in
+	if in.CELMatches != nil {
+		in, out := &in.CELMatches, &out.CELMatches
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	if in.JSON != nil {
 		in, out := &in.JSON, &out.JSON
 		*out = make(map[string]string, len(*in))
@@ -1745,6 +1770,11 @@ func (in *OIDC) DeepCopy() *OIDC {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *OpenTelemetryAccessLog) DeepCopyInto(out *OpenTelemetryAccessLog) {
 	*out = *in
+	if in.CELMatches != nil {
+		in, out := &in.CELMatches, &out.CELMatches
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	if in.Text != nil {
 		in, out := &in.Text, &out.Text
 		*out = new(string)
@@ -2709,6 +2739,11 @@ func (in *TLSUpstreamConfig) DeepCopy() *TLSUpstreamConfig {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *TextAccessLog) DeepCopyInto(out *TextAccessLog) {
 	*out = *in
+	if in.CELMatches != nil {
+		in, out := &in.CELMatches, &out.CELMatches
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 	if in.Format != nil {
 		in, out := &in.Format, &out.Format
 		*out = new(string)
diff --git a/internal/xds/translator/accesslog.go b/internal/xds/translator/accesslog.go
index 85151eaca..01c448b65 100644
--- a/internal/xds/translator/accesslog.go
+++ b/internal/xds/translator/accesslog.go
@@ -131,6 +131,7 @@ func buildXdsAccessLog(al *ir.AccessLog, forListener bool) []*accesslog.AccessLo
 			ConfigType: &accesslog.AccessLog_TypedConfig{
 				TypedConfig: accesslogAny,
 			},
+			Filter: buildAccessLogFilter(text.CELMatches, forListener),
 		})
 	}
 	// handle json file access logs
@@ -173,6 +174,7 @@ func buildXdsAccessLog(al *ir.AccessLog, forListener bool) []*accesslog.AccessLo
 			ConfigType: &accesslog.AccessLog_TypedConfig{
 				TypedConfig: accesslogAny,
 			},
+			Filter: buildAccessLogFilter(json.CELMatches, forListener),
 		})
 	}
 	// handle ALS access logs
@@ -207,6 +209,7 @@ func buildXdsAccessLog(al *ir.AccessLog, forListener bool) []*accesslog.AccessLo
 				ConfigType: &accesslog.AccessLog_TypedConfig{
 					TypedConfig: accesslogAny,
 				},
+				Filter: buildAccessLogFilter(als.CELMatches, forListener),
 			})
 		case egv1a1.ALSEnvoyProxyAccessLogTypeTCP:
 			alCfg := &grpcaccesslog.TcpGrpcAccessLogConfig{
@@ -219,6 +222,7 @@ func buildXdsAccessLog(al *ir.AccessLog, forListener bool) []*accesslog.AccessLo
 				ConfigType: &accesslog.AccessLog_TypedConfig{
 					TypedConfig: accesslogAny,
 				},
+				Filter: buildAccessLogFilter(als.CELMatches, forListener),
 			})
 		}
 	}
@@ -266,24 +270,10 @@ func buildXdsAccessLog(al *ir.AccessLog, forListener bool) []*accesslog.AccessLo
 			ConfigType: &accesslog.AccessLog_TypedConfig{
 				TypedConfig: accesslogAny,
 			},
+			Filter: buildAccessLogFilter(otel.CELMatches, forListener),
 		})
 	}
 
-	// add filter for access logs
-	filters := make([]*accesslog.AccessLogFilter, 0)
-	for _, expr := range al.CELMatches {
-		filters = append(filters, celAccessLogFilter(expr))
-	}
-	if forListener {
-		filters = append(filters, listenerAccessLogFilter)
-	}
-
-	f := buildAccessLogFilter(filters...)
-
-	for _, log := range accessLogs {
-		log.Filter = f
-	}
-
 	return accessLogs
 }
 
@@ -302,19 +292,28 @@ func celAccessLogFilter(expr string) *accesslog.AccessLogFilter {
 	}
 }
 
-func buildAccessLogFilter(f ...*accesslog.AccessLogFilter) *accesslog.AccessLogFilter {
-	if len(f) == 0 {
+func buildAccessLogFilter(exprs []string, forListener bool) *accesslog.AccessLogFilter {
+	// add filter for access logs
+	var filters []*accesslog.AccessLogFilter
+	for _, expr := range exprs {
+		filters = append(filters, celAccessLogFilter(expr))
+	}
+	if forListener {
+		filters = append(filters, listenerAccessLogFilter)
+	}
+
+	if len(filters) == 0 {
 		return nil
 	}
 
-	if len(f) == 1 {
-		return f[0]
+	if len(filters) == 1 {
+		return filters[0]
 	}
 
 	return &accesslog.AccessLogFilter{
 		FilterSpecifier: &accesslog.AccessLogFilter_AndFilter{
 			AndFilter: &accesslog.AndFilter{
-				Filters: f,
+				Filters: filters,
 			},
 		},
 	}
diff --git a/internal/xds/translator/extproc.go b/internal/xds/translator/extproc.go
index 9d4779b41..2eeeb5855 100644
--- a/internal/xds/translator/extproc.go
+++ b/internal/xds/translator/extproc.go
@@ -51,7 +51,7 @@ func (*extProc) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPLi
 			continue
 		}
 
-		for _, ep := range route.ExtProcs {
+		for _, ep := range route.EnvoyExtensions.ExtProcs {
 			if hcmContainsFilter(mgr, extProcFilterName(ep)) {
 				continue
 			}
@@ -156,7 +156,7 @@ func routeContainsExtProc(irRoute *ir.HTTPRoute) bool {
 		return false
 	}
 
-	return len(irRoute.ExtProcs) > 0
+	return irRoute.EnvoyExtensions != nil && len(irRoute.EnvoyExtensions.ExtProcs) > 0
 }
 
 // patchResources patches the cluster resources for the external services.
@@ -173,8 +173,8 @@ func (*extProc) patchResources(tCtx *types.ResourceVersionTable,
 			continue
 		}
 
-		for i := range route.ExtProcs {
-			ep := route.ExtProcs[i]
+		for i := range route.EnvoyExtensions.ExtProcs {
+			ep := route.EnvoyExtensions.ExtProcs[i]
 			if err := createExtServiceXDSCluster(
 				&ep.Destination, tCtx); err != nil && !errors.Is(
 				err, ErrXdsClusterExists) {
@@ -196,8 +196,11 @@ func (*extProc) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error {
 	if irRoute == nil {
 		return errors.New("ir route is nil")
 	}
+	if irRoute.EnvoyExtensions == nil {
+		return nil
+	}
 
-	for _, ep := range irRoute.ExtProcs {
+	for _, ep := range irRoute.EnvoyExtensions.ExtProcs {
 		filterName := extProcFilterName(ep)
 		if err := enableFilterOnRoute(route, filterName); err != nil {
 			return err
diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go
index 139b359a1..65d60d251 100644
--- a/internal/xds/translator/route.go
+++ b/internal/xds/translator/route.go
@@ -505,12 +505,12 @@ func buildHashPolicy(httpRoute *ir.HTTPRoute) []*routev3.RouteAction_HashPolicy
 			hashPolicy.GetCookie().Ttl = durationpb.New(ch.Cookie.TTL.Duration)
 		}
 		if ch.Cookie.Attributes != nil {
-			attributes := make([]*routev3.RouteAction_HashPolicy_CookieAttribute, len(ch.Cookie.Attributes))
-			i := 0
+			attributes := make([]*routev3.RouteAction_HashPolicy_CookieAttribute, 0, len(ch.Cookie.Attributes))
 			for name, value := range ch.Cookie.Attributes {
-				attributes[i].Name = name
-				attributes[i].Value = value
-				i++
+				attributes = append(attributes, &routev3.RouteAction_HashPolicy_CookieAttribute{
+					Name:  name,
+					Value: value,
+				})
 			}
 			hashPolicy.GetCookie().Attributes = attributes
 		}
diff --git a/internal/xds/translator/wasm.go b/internal/xds/translator/wasm.go
index 01d7411c6..4d6434c95 100644
--- a/internal/xds/translator/wasm.go
+++ b/internal/xds/translator/wasm.go
@@ -53,7 +53,7 @@ func (*wasm) patchHCM(mgr *hcmv3.HttpConnectionManager, irListener *ir.HTTPListe
 		if !routeContainsWasm(route) {
 			continue
 		}
-		for _, ep := range route.Wasms {
+		for _, ep := range route.EnvoyExtensions.Wasms {
 			if hcmContainsFilter(mgr, wasmFilterName(ep)) {
 				continue
 			}
@@ -161,7 +161,7 @@ func routeContainsWasm(irRoute *ir.HTTPRoute) bool {
 		return false
 	}
 
-	return len(irRoute.Wasms) > 0
+	return irRoute.EnvoyExtensions != nil && len(irRoute.EnvoyExtensions.Wasms) > 0
 }
 
 // patchResources patches the cluster resources for the http wasm code source.
@@ -181,8 +181,11 @@ func (*wasm) patchRoute(route *routev3.Route, irRoute *ir.HTTPRoute) error {
 	if irRoute == nil {
 		return errors.New("ir route is nil")
 	}
+	if irRoute.EnvoyExtensions == nil {
+		return nil
+	}
 
-	for _, ep := range irRoute.Wasms {
+	for _, ep := range irRoute.EnvoyExtensions.Wasms {
 		filterName := wasmFilterName(ep)
 		if err := enableFilterOnRoute(route, filterName); err != nil {
 			return err
diff --git a/tools/make/kube.mk b/tools/make/kube.mk
index 2258aa90f..4ec344358 100644
--- a/tools/make/kube.mk
+++ b/tools/make/kube.mk
@@ -141,17 +141,24 @@ install-ratelimit:
 	tools/hack/deployment-exists.sh "app.kubernetes.io/name=envoy-ratelimit" "envoy-gateway-system"
 	kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-ratelimit --for=condition=Available
 
-.PHONY: run-e2e
-run-e2e: ## Run e2e tests
+.PHONY: e2e-prepare
+e2e-prepare: ## Prepare the environment for running e2e tests
 	@$(LOG_TARGET)
 	kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-ratelimit --for=condition=Available
 	kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available
 	kubectl apply -f test/config/gatewayclass.yaml
+
+.PHONY: run-e2e
+run-e2e: e2e-prepare ## Run e2e tests
+	@$(LOG_TARGET)
 ifeq ($(E2E_RUN_TEST),)
 	go test $(E2E_TEST_ARGS) ./test/e2e --gateway-class=envoy-gateway --debug=true --cleanup-base-resources=false
 	go test $(E2E_TEST_ARGS) ./test/e2e/merge_gateways --gateway-class=merge-gateways --debug=true --cleanup-base-resources=false
 	go test $(E2E_TEST_ARGS) ./test/e2e/multiple_gc --debug=true --cleanup-base-resources=true
 	go test $(E2E_TEST_ARGS) ./test/e2e/upgrade --gateway-class=upgrade --debug=true --cleanup-base-resources=$(E2E_CLEANUP)
+else
+	go test $(E2E_TEST_ARGS) ./test/e2e --gateway-class=envoy-gateway --debug=true --cleanup-base-resources=$(E2E_CLEANUP) \
+		--run-test $(E2E_RUN_TEST)
 endif
 
 .PHONY: run-benchmark


Test patch:
diff --git a/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml
index c1425425b..643df0503 100644
--- a/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml
+++ b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml
@@ -174,6 +174,7 @@ xdsIR:
           - weight: 1
         directResponse:
           statusCode: 500
+        envoyExtensions: {}
         hostname: '*'
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-override-replace.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-override-replace.in.yaml
index b9f40aee0..0b844dc0c 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-override-replace.in.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-override-replace.in.yaml
@@ -52,6 +52,25 @@ httpRoutes:
       backendRefs:
       - name: service-1
         port: 8080
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-3
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/baz"
+      backendRefs:
+      - name: service-1
+        port: 8080
 backendTrafficPolicies:
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: BackendTrafficPolicy
@@ -85,3 +104,13 @@ backendTrafficPolicies:
       type: ConsistentHash
       consistentHash:
         type: SourceIP
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    namespace: default
+    name: policy-for-route-3
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-override-replace.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-override-replace.out.yaml
index 59da46177..8aafd70c0 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-override-replace.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-override-replace.out.yaml
@@ -29,6 +29,32 @@ backendTrafficPolicies:
         status: "True"
         type: Accepted
       controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-route-3
+    namespace: default
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+      conditions:
+      - lastTransitionTime: null
+        message: Policy has been accepted.
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: BackendTrafficPolicy
   metadata:
@@ -63,7 +89,7 @@ backendTrafficPolicies:
         type: Accepted
       - lastTransitionTime: null
         message: 'This policy is being overridden by other backendTrafficPolicies
-          for these routes: [default/httproute-1]'
+          for these routes: [default/httproute-1 default/httproute-3]'
         reason: Overridden
         status: "True"
         type: Overridden
@@ -86,7 +112,7 @@ gateways:
       protocol: HTTP
   status:
     listeners:
-    - attachedRoutes: 2
+    - attachedRoutes: 3
       conditions:
       - lastTransitionTime: null
         message: Sending translated listener configuration to the data plane
@@ -186,6 +212,44 @@ httpRoutes:
         name: gateway-1
         namespace: envoy-gateway
         sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-3
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /baz
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
 infraIR:
   envoy-gateway/gateway-1:
     proxy:
@@ -276,3 +340,24 @@ xdsIR:
               maxConnectionDuration: 22s
             tcp:
               connectTimeout: 20s
+      - destination:
+          name: httproute/default/httproute-3/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            protocol: HTTP
+            weight: 1
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-3
+          namespace: default
+        name: httproute/default/httproute-3/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /baz
+        traffic: {}
diff --git a/internal/gatewayapi/testdata/custom-filter-order.out.yaml b/internal/gatewayapi/testdata/custom-filter-order.out.yaml
index fcab6d9f5..6967bf280 100644
--- a/internal/gatewayapi/testdata/custom-filter-order.out.yaml
+++ b/internal/gatewayapi/testdata/custom-filter-order.out.yaml
@@ -246,6 +246,30 @@ xdsIR:
           - weight: 1
         directResponse:
           statusCode: 500
+        envoyExtensions:
+          wasms:
+          - config:
+              parameter1:
+                key1: value1
+                key2: value2
+              parameter2: value3
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
+              servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
+              sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
+            wasmName: wasm-filter-1
+          - config:
+              parameter1: value1
+              parameter2: value2
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm
+              servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm
+              sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
+            wasmName: wasm-filter-2
         hostname: www.example.com
         isHTTP2: false
         metadata:
@@ -292,26 +316,3 @@ xdsIR:
               name: example2
               remoteJWKS:
                 uri: http://two.example.com/jwt/public-key/jwks.json
-        wasm:
-        - config:
-            parameter1:
-              key1: value1
-              key2: value2
-            parameter2: value3
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
-            servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
-            sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
-          wasmName: wasm-filter-1
-        - config:
-            parameter1: value1
-            parameter2: value2
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm
-            servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm
-            sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
-          wasmName: wasm-filter-2
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml
index 3ad36f071..f9c917559 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.in.yaml
@@ -73,6 +73,25 @@ httpRoutes:
       backendRefs:
       - name: service-1
         port: 8080
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-3
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/baz"
+      backendRefs:
+      - name: service-1
+        port: 8080
 envoyExtensionPolicies:
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: EnvoyExtensionPolicy
@@ -102,3 +121,13 @@ envoyExtensionPolicies:
     - backendRefs:
       - name: grpc-backend-2
         port: 8000
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: EnvoyExtensionPolicy
+  metadata:
+    namespace: default
+    name: policy-for-route-3
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml
index 08a615219..4f055e7bc 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-override-replace.out.yaml
@@ -29,6 +29,32 @@ envoyExtensionPolicies:
         status: "True"
         type: Accepted
       controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: EnvoyExtensionPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-route-3
+    namespace: default
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+      conditions:
+      - lastTransitionTime: null
+        message: Policy has been accepted.
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: EnvoyExtensionPolicy
   metadata:
@@ -59,7 +85,7 @@ envoyExtensionPolicies:
         type: Accepted
       - lastTransitionTime: null
         message: 'This policy is being overridden by other envoyExtensionPolicies
-          for these routes: [default/httproute-1]'
+          for these routes: [default/httproute-1 default/httproute-3]'
         reason: Overridden
         status: "True"
         type: Overridden
@@ -82,7 +108,7 @@ gateways:
       protocol: HTTP
   status:
     listeners:
-    - attachedRoutes: 2
+    - attachedRoutes: 3
       conditions:
       - lastTransitionTime: null
         message: Sending translated listener configuration to the data plane
@@ -182,6 +208,44 @@ httpRoutes:
         name: gateway-1
         namespace: envoy-gateway
         sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-3
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /baz
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
 infraIR:
   envoy-gateway/gateway-1:
     proxy:
@@ -228,14 +292,15 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
-        extProc:
-        - authority: grpc-backend-2.default:8000
-          destination:
-            name: envoyextensionpolicy/default/policy-for-route-1/0
-            settings:
-            - protocol: GRPC
-              weight: 1
-          name: envoyextensionpolicy/default/policy-for-route-1/extproc/0
+        envoyExtensions:
+          extProcs:
+          - authority: grpc-backend-2.default:8000
+            destination:
+              name: envoyextensionpolicy/default/policy-for-route-1/0
+              settings:
+              - protocol: GRPC
+                weight: 1
+            name: envoyextensionpolicy/default/policy-for-route-1/extproc/0
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
@@ -256,14 +321,15 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
-        extProc:
-        - authority: grpc-backend.envoy-gateway:9000
-          destination:
-            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0
-            settings:
-            - protocol: GRPC
-              weight: 1
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/extproc/0
+        envoyExtensions:
+          extProcs:
+          - authority: grpc-backend.envoy-gateway:9000
+            destination:
+              name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0
+              settings:
+              - protocol: GRPC
+                weight: 1
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/extproc/0
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         metadata:
@@ -275,3 +341,24 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /bar
+      - destination:
+          name: httproute/default/httproute-3/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            protocol: HTTP
+            weight: 1
+        envoyExtensions: {}
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-3
+          namespace: default
+        name: httproute/default/httproute-3/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /baz
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml
index ef83112c1..0c4264fd4 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml
@@ -561,6 +561,7 @@ xdsIR:
           - weight: 1
         directResponse:
           statusCode: 500
+        envoyExtensions: {}
         hostname: '*'
         isHTTP2: false
         metadata:
@@ -598,6 +599,7 @@ xdsIR:
           - weight: 1
         directResponse:
           statusCode: 500
+        envoyExtensions: {}
         headerMatches:
         - distinct: false
           exact: foo
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml
index 638084126..4bfbd4e7d 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-backendtlspolicy.out.yaml
@@ -304,25 +304,26 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
-        extProc:
-        - authority: grpc-backend-2.default:9000
-          destination:
-            name: envoyextensionpolicy/default/policy-for-http-route/0
-            settings:
-            - addressType: IP
-              endpoints:
-              - host: 8.8.8.8
-                port: 9000
-              protocol: GRPC
-              tls:
-                caCertificate:
-                  certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
-                  name: policy-btls-grpc-2/default-ca
-                sni: grpc-backend-2
-              weight: 1
-          name: envoyextensionpolicy/default/policy-for-http-route/extproc/0
-          requestHeaderProcessing: true
-          responseHeaderProcessing: true
+        envoyExtensions:
+          extProcs:
+          - authority: grpc-backend-2.default:9000
+            destination:
+              name: envoyextensionpolicy/default/policy-for-http-route/0
+              settings:
+              - addressType: IP
+                endpoints:
+                - host: 8.8.8.8
+                  port: 9000
+                protocol: GRPC
+                tls:
+                  caCertificate:
+                    certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+                    name: policy-btls-grpc-2/default-ca
+                  sni: grpc-backend-2
+                weight: 1
+            name: envoyextensionpolicy/default/policy-for-http-route/extproc/0
+            requestHeaderProcessing: true
+            responseHeaderProcessing: true
         hostname: www.foo.com
         isHTTP2: false
         metadata:
@@ -343,26 +344,27 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
-        extProc:
-        - authority: grpc-backend.envoy-gateway:8000
-          destination:
-            name: envoyextensionpolicy/default/policy-for-gateway/0
-            settings:
-            - addressType: IP
-              protocol: GRPC
-              tls:
-                caCertificate:
-                  certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
-                  name: policy-btls-grpc/envoy-gateway-ca
-                sni: grpc-backend
-              weight: 1
-          failOpen: true
-          messageTimeout: 5s
-          name: envoyextensionpolicy/default/policy-for-gateway/extproc/0
-          requestBodyProcessingMode: Buffered
-          requestHeaderProcessing: true
-          responseBodyProcessingMode: Streamed
-          responseHeaderProcessing: true
+        envoyExtensions:
+          extProcs:
+          - authority: grpc-backend.envoy-gateway:8000
+            destination:
+              name: envoyextensionpolicy/default/policy-for-gateway/0
+              settings:
+              - addressType: IP
+                protocol: GRPC
+                tls:
+                  caCertificate:
+                    certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+                    name: policy-btls-grpc/envoy-gateway-ca
+                  sni: grpc-backend
+                weight: 1
+            failOpen: true
+            messageTimeout: 5s
+            name: envoyextensionpolicy/default/policy-for-gateway/extproc/0
+            requestBodyProcessingMode: Buffered
+            requestHeaderProcessing: true
+            responseBodyProcessingMode: Streamed
+            responseHeaderProcessing: true
         hostname: www.bar.com
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml
index d71c0ab29..fda8a8185 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-extproc-with-multiple-backendrefs.out.yaml
@@ -304,43 +304,44 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
-        extProc:
-        - authority: grpc-backend.envoy-gateway:8000
-          destination:
-            name: envoyextensionpolicy/default/policy-for-http-route/0
-            settings:
-            - addressType: IP
-              protocol: GRPC
-              tls:
-                caCertificate:
-                  certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
-                  name: policy-btls-grpc/envoy-gateway-ca
-                sni: grpc-backend
-              weight: 1
-            - addressType: IP
-              endpoints:
-              - host: 8.8.8.8
-                port: 9000
-              protocol: GRPC
-              weight: 1
-            - addressType: IP
-              endpoints:
-              - host: 1.1.1.1
-                port: 3001
-              protocol: GRPC
-              weight: 1
-            - addressType: IP
-              endpoints:
-              - host: 2.2.2.2
-                port: 3443
-              protocol: GRPC
-              tls:
-                caCertificate:
-                  certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
-                  name: policy-btls-backend-ip/envoy-gateway-ca
-                sni: ip-backend
-              weight: 1
-          name: envoyextensionpolicy/default/policy-for-http-route/extproc/0
+        envoyExtensions:
+          extProcs:
+          - authority: grpc-backend.envoy-gateway:8000
+            destination:
+              name: envoyextensionpolicy/default/policy-for-http-route/0
+              settings:
+              - addressType: IP
+                protocol: GRPC
+                tls:
+                  caCertificate:
+                    certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+                    name: policy-btls-grpc/envoy-gateway-ca
+                  sni: grpc-backend
+                weight: 1
+              - addressType: IP
+                endpoints:
+                - host: 8.8.8.8
+                  port: 9000
+                protocol: GRPC
+                weight: 1
+              - addressType: IP
+                endpoints:
+                - host: 1.1.1.1
+                  port: 3001
+                protocol: GRPC
+                weight: 1
+              - addressType: IP
+                endpoints:
+                - host: 2.2.2.2
+                  port: 3443
+                protocol: GRPC
+                tls:
+                  caCertificate:
+                    certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lVQWw2VUtJdUttenRlODFjbGx6NVBmZE4ySWxJd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHQTFVRUNnd0dhM1ZpWldSaU1CNFhEVEl6TVRBdwpNakExTkRFMU4xb1hEVEkwTVRBd01UQTFOREUxTjFvd0l6RVFNQTRHQTFVRUF3d0hiWGxqYVdWdWRERVBNQTBHCkExVUVDZ3dHYTNWaVpXUmlNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXdTVGMKMXlqOEhXNjJueW5rRmJYbzRWWEt2MmpDMFBNN2RQVmt5ODdGd2VaY1RLTG9XUVZQUUUycDJrTERLNk9Fc3ptTQp5eXIreHhXdHlpdmVyZW1yV3FuS2tOVFloTGZZUGhnUWtjemliN2VVYWxtRmpVYmhXZEx2SGFrYkVnQ29kbjNiCmt6NTdtSW5YMlZwaURPS2c0a3lIZml1WFdwaUJxckN4MEtOTHB4bzNERVFjRmNzUVRlVEh6aDQ3NTJHVjA0UlUKVGkvR0VXeXpJc2w0Umc3dEd0QXdtY0lQZ1VOVWZZMlEzOTBGR3FkSDRhaG4rbXcvNmFGYlczMVc2M2Q5WUpWcQppb3lPVmNhTUlwTTVCL2M3UWM4U3VoQ0kxWUdoVXlnNGNSSExFdzVWdGlraW95RTNYMDRrbmEzalFBajU0WWJSCmJwRWhjMzVhcEtMQjIxSE9VUUlEQVFBQm8xTXdVVEFkQmdOVkhRNEVGZ1FVeXZsMFZJNXZKVlN1WUZYdTdCNDgKNlBiTUVBb3dId1lEVlIwakJCZ3dGb0FVeXZsMFZJNXZKVlN1WUZYdTdCNDg2UGJNRUFvd0R3WURWUjBUQVFILwpCQVV3QXdFQi96QU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFNTHhyZ0ZWTXVOUnEyd0F3Y0J0N1NuTlI1Q2Z6CjJNdlhxNUVVbXVhd0lVaTlrYVlqd2RWaURSRUdTams3SlcxN3ZsNTc2SGpEa2RmUndpNEUyOFN5ZFJJblpmNkoKaThIWmNaN2NhSDZEeFIzMzVmZ0hWekxpNU5pVGNlL09qTkJRelEyTUpYVkRkOERCbUc1ZnlhdEppT0pRNGJXRQpBN0ZsUDBSZFAzQ08zR1dFME01aVhPQjJtMXFXa0UyZXlPNFVIdndUcU5RTGRyZEFYZ0RRbGJhbTllNEJHM0dnCmQvNnRoQWtXRGJ0L1FOVCtFSkhEQ3ZoRFJLaDFSdUdIeWcrWSsvbmViVFdXckZXc2t0UnJiT29IQ1ppQ3BYSTEKM2VYRTZudDBZa2d0RHhHMjJLcW5ocEFnOWdVU3MyaGxob3h5dmt6eUYwbXU2TmhQbHdBZ25xNysvUT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+                    name: policy-btls-backend-ip/envoy-gateway-ca
+                  sni: ip-backend
+                weight: 1
+            name: envoyextensionpolicy/default/policy-for-http-route/extproc/0
         hostname: www.foo.com
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml
index 24ef89d27..4abc9f590 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml
@@ -228,6 +228,30 @@ xdsIR:
           - weight: 1
         directResponse:
           statusCode: 500
+        envoyExtensions:
+          wasms:
+          - config:
+              parameter1:
+                key1: value1
+                key2: value2
+              parameter2: value3
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
+              servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
+              sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
+            wasmName: wasm-filter-1
+          - config:
+              parameter1: value1
+              parameter2: value2
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm
+              servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm
+              sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
+            wasmName: wasm-filter-2
         hostname: www.example.com
         isHTTP2: false
         metadata:
@@ -239,35 +263,36 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /foo
-        wasm:
-        - config:
-            parameter1:
-              key1: value1
-              key2: value2
-            parameter2: value3
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
-            servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
-            sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
-          wasmName: wasm-filter-1
-        - config:
-            parameter1: value1
-            parameter2: value2
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm
-            servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm
-            sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
-          wasmName: wasm-filter-2
       - destination:
           name: httproute/envoy-gateway/httproute-2/rule/0
           settings:
           - weight: 1
         directResponse:
           statusCode: 500
+        envoyExtensions:
+          wasms:
+          - config:
+              parameter1:
+                key1: value1
+                key2: value2
+              parameter2: value3
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
+              servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
+              sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
+            wasmName: wasm-filter-1
+          - config:
+              parameter1: value1
+              parameter2: value2
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm
+              servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm
+              sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
+            wasmName: wasm-filter-2
         hostname: www.example.com
         isHTTP2: false
         metadata:
@@ -279,26 +304,3 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /bar
-        wasm:
-        - config:
-            parameter1:
-              key1: value1
-              key2: value2
-            parameter2: value3
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
-            servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
-            sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
-          wasmName: wasm-filter-1
-        - config:
-            parameter1: value1
-            parameter2: value2
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: https://www.example.com/wasm-filter-2.wasm
-            servingURL: https://envoy-gateway:18002/593e4cc60a7e0fa4d4f86531a5e20e785213a52000f056a7a8b5c5afcb908052.wasm
-            sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
-          wasmName: wasm-filter-2
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.out.yaml
index d7627ea33..68cfaf925 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm.out.yaml
@@ -265,6 +265,21 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        envoyExtensions:
+          wasms:
+          - config:
+              parameter1:
+                key1: value1
+              parameter2:
+                key2:
+                  key3: value3
+            failOpen: true
+            httpWasmCode:
+              originalDownloadingURL: https://www.test.com/wasm-filter-4.wasm
+              servingURL: https://envoy-gateway:18002/fe571e7b1ef5dc626ceb2c2c86782a134a92989a2643485238951696ae4334c3.wasm
+              sha256: a1f0b78b8c1320690327800e3a5de10e7dbba7b6c752e702193a395a52c727b6
+            name: envoyextensionpolicy/default/policy-for-http-route/wasm/0
+            wasmName: wasm-filter-4
         hostname: www.example.com
         isHTTP2: false
         metadata:
@@ -276,20 +291,6 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /foo
-        wasm:
-        - config:
-            parameter1:
-              key1: value1
-            parameter2:
-              key2:
-                key3: value3
-          failOpen: true
-          httpWasmCode:
-            originalDownloadingURL: https://www.test.com/wasm-filter-4.wasm
-            servingURL: https://envoy-gateway:18002/fe571e7b1ef5dc626ceb2c2c86782a134a92989a2643485238951696ae4334c3.wasm
-            sha256: a1f0b78b8c1320690327800e3a5de10e7dbba7b6c752e702193a395a52c727b6
-          name: envoyextensionpolicy/default/policy-for-http-route/wasm/0
-          wasmName: wasm-filter-4
       - destination:
           name: httproute/default/httproute-2/rule/0
           settings:
@@ -299,6 +300,39 @@ xdsIR:
               port: 8080
             protocol: HTTP
             weight: 1
+        envoyExtensions:
+          wasms:
+          - config:
+              parameter1:
+                key1: value1
+                key2: value2
+              parameter2: value3
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
+              servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
+              sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
+            wasmName: wasm-filter-1
+          - config:
+              parameter1: value1
+              parameter2: value2
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: oci://www.example.com/wasm-filter-2:v1.0.0
+              servingURL: https://envoy-gateway:18002/7abf116e5cd5a20389604a5ba0f3bd04fdf76f92181fe67506b42c2ee596d3fd.wasm
+              sha256: 314100af781b98a8ca175d5bf90a8bf76576e20a2f397a88223404edc6ebfd46
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
+            rootID: my-root-id
+            wasmName: wasm-filter-2
+          - config: null
+            failOpen: false
+            httpWasmCode:
+              originalDownloadingURL: oci://www.example.com:8080/wasm-filter-3:latest
+              servingURL: https://envoy-gateway:18002/42d30b4a4cc631415e6e48c02d244700da327201eb273f752cacf745715b31d9.wasm
+              sha256: 2a19e4f337e5223d7287e7fccd933fb01905deaff804292e5257f8c681b82bee
+            name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/2
+            wasmName: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/2
         hostname: www.example.com
         isHTTP2: false
         metadata:
@@ -310,35 +344,3 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /bar
-        wasm:
-        - config:
-            parameter1:
-              key1: value1
-              key2: value2
-            parameter2: value3
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
-            servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
-            sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
-          wasmName: wasm-filter-1
-        - config:
-            parameter1: value1
-            parameter2: value2
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: oci://www.example.com/wasm-filter-2:v1.0.0
-            servingURL: https://envoy-gateway:18002/7abf116e5cd5a20389604a5ba0f3bd04fdf76f92181fe67506b42c2ee596d3fd.wasm
-            sha256: 314100af781b98a8ca175d5bf90a8bf76576e20a2f397a88223404edc6ebfd46
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
-          rootID: my-root-id
-          wasmName: wasm-filter-2
-        - config: null
-          failOpen: false
-          httpWasmCode:
-            originalDownloadingURL: oci://www.example.com:8080/wasm-filter-3:latest
-            servingURL: https://envoy-gateway:18002/42d30b4a4cc631415e6e48c02d244700da327201eb273f752cacf745715b31d9.wasm
-            sha256: 2a19e4f337e5223d7287e7fccd933fb01905deaff804292e5257f8c681b82bee
-          name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/2
-          wasmName: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/2
diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-cel.in.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-cel.in.yaml
index 3d9f52018..4f6c7b369 100644
--- a/internal/gatewayapi/testdata/envoyproxy-accesslog-cel.in.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-cel.in.yaml
@@ -24,6 +24,14 @@ envoyProxyForGatewayClass:
               port: 4317
               resources:
                 k8s.cluster.name: "cluster-1"
+        - sinks:
+          - type: ALS
+            als:
+              backendRefs:
+              - name: envoy-als
+                namespace: monitoring
+                port: 9000
+              type: TCP
     provider:
       type: Kubernetes
       kubernetes:
@@ -87,3 +95,36 @@ gateways:
       allowedRoutes:
         namespaces:
           from: Same
+services:
+- apiVersion: v1
+  kind: Service
+  metadata:
+    name: envoy-als
+    namespace: monitoring
+  spec:
+    type: ClusterIP
+    ports:
+    - name: grpc
+      port: 9000
+      appProtocol: grpc
+      protocol: TCP
+      targetPort: 9000
+endpointSlices:
+- apiVersion: discovery.k8s.io/v1
+  kind: EndpointSlice
+  metadata:
+    name: endpointslice-envoy-als
+    namespace: monitoring
+    labels:
+      kubernetes.io/service-name: envoy-als
+  addressType: IPv4
+  ports:
+  - name: grpc
+    appProtocol: grpc
+    protocol: TCP
+    port: 9090
+  endpoints:
+  - addresses:
+    - "10.240.0.10"
+    conditions:
+      ready: true
diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-cel.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-cel.out.yaml
index 5802c511e..4161575dd 100644
--- a/internal/gatewayapi/testdata/envoyproxy-accesslog-cel.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-cel.out.yaml
@@ -118,6 +118,14 @@ infraIR:
                     resources:
                       k8s.cluster.name: cluster-1
                   type: OpenTelemetry
+              - sinks:
+                - als:
+                    backendRefs:
+                    - name: envoy-als
+                      namespace: monitoring
+                      port: 9000
+                    type: TCP
+                  type: ALS
         status: {}
       listeners:
       - address: null
@@ -135,10 +143,21 @@ infraIR:
 xdsIR:
   envoy-gateway/gateway-1:
     accessLog:
-      celMatches:
-      - response.code >= 400
+      als:
+      - destination:
+          name: accesslog_als_1_0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 10.240.0.10
+              port: 9090
+            protocol: GRPC
+        name: envoy-gateway-system/test
+        type: TCP
       openTelemetry:
       - authority: otel-collector.monitoring.svc.cluster.local
+        celMatches:
+        - response.code >= 400
         destination:
           name: accesslog_otel_0_1
           settings:
@@ -152,7 +171,9 @@ xdsIR:
         text: |
           [%START_TIME%] "%REQ(:METHOD)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n
       text:
-      - format: |
+      - celMatches:
+        - response.code >= 400
+        format: |
           [%START_TIME%] "%REQ(:METHOD)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"\n
         path: /dev/stdout
     http:
diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-without-format.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-without-format.out.yaml
index f62207ce2..43505266e 100644
--- a/internal/gatewayapi/testdata/envoyproxy-accesslog-without-format.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-without-format.out.yaml
@@ -102,8 +102,7 @@ infraIR:
           telemetry:
             accessLog:
               settings:
-              - format: null
-                sinks:
+              - sinks:
                 - file:
                     path: /dev/stdout
                   type: File
diff --git a/internal/gatewayapi/testdata/securitypolicy-override-replace.in.yaml b/internal/gatewayapi/testdata/securitypolicy-override-replace.in.yaml
index debfe1dd4..bf3bfcedc 100644
--- a/internal/gatewayapi/testdata/securitypolicy-override-replace.in.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-override-replace.in.yaml
@@ -52,6 +52,25 @@ httpRoutes:
       backendRefs:
       - name: service-1
         port: 8080
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-3
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/baz"
+      backendRefs:
+      - name: service-1
+        port: 8080
 securityPolicies:
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: SecurityPolicy
@@ -113,3 +132,13 @@ securityPolicies:
       - "x-header-7"
       - "x-header-8"
       maxAge: 2000s
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: SecurityPolicy
+  metadata:
+    namespace: default
+    name: policy-for-route-3
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
diff --git a/internal/gatewayapi/testdata/securitypolicy-override-replace.out.yaml b/internal/gatewayapi/testdata/securitypolicy-override-replace.out.yaml
index 7c0dcab60..c6f720655 100644
--- a/internal/gatewayapi/testdata/securitypolicy-override-replace.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-override-replace.out.yaml
@@ -16,7 +16,7 @@ gateways:
       protocol: HTTP
   status:
     listeners:
-    - attachedRoutes: 2
+    - attachedRoutes: 3
       conditions:
       - lastTransitionTime: null
         message: Sending translated listener configuration to the data plane
@@ -116,6 +116,44 @@ httpRoutes:
         name: gateway-1
         namespace: envoy-gateway
         sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-3
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /baz
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
 infraIR:
   envoy-gateway/gateway-1:
     proxy:
@@ -173,6 +211,32 @@ securityPolicies:
         status: "True"
         type: Accepted
       controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: SecurityPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-route-3
+    namespace: default
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-3
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: http
+      conditions:
+      - lastTransitionTime: null
+        message: Policy has been accepted.
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: SecurityPolicy
   metadata:
@@ -225,7 +289,7 @@ securityPolicies:
         type: Accepted
       - lastTransitionTime: null
         message: 'This policy is being overridden by other securityPolicies for these
-          routes: [default/httproute-1]'
+          routes: [default/httproute-1 default/httproute-3]'
         reason: Overridden
         status: "True"
         type: Overridden
@@ -343,3 +407,24 @@ xdsIR:
               name: example1
               remoteJWKS:
                 uri: https://one.example.com/jwt/public-key/jwks.json
+      - destination:
+          name: httproute/default/httproute-3/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            protocol: HTTP
+            weight: 1
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-3
+          namespace: default
+        name: httproute/default/httproute-3/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /baz
+        security: {}
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-cel.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-cel.yaml
index b0623fd08..e9cff901d 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog-cel.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-cel.yaml
@@ -1,13 +1,15 @@
 name: "accesslog"
 accesslog:
-  celMatches:
-  - response.code >= 400
   text:
   - path: "/dev/stdout"
+    celMatches:
+    - response.code >= 400
     format: |
       [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"
   json:
   - path: "/dev/stdout"
+    celMatches:
+    - response.code >= 400
     json:
       start_time: "%START_TIME%"
       method: "%REQ(:METHOD)%"
@@ -22,6 +24,8 @@ accesslog:
     resources:
       "cluster_name": "cluster1"
     authority: "otel-collector.default.svc.cluster.local"
+    celMatches:
+    - response.code >= 400
     destination:
       name: "accesslog-0"
       settings:
diff --git a/internal/xds/translator/testdata/in/xds-ir/accesslog-multi-cel.yaml b/internal/xds/translator/testdata/in/xds-ir/accesslog-multi-cel.yaml
index 704c19863..fab193fe5 100644
--- a/internal/xds/translator/testdata/in/xds-ir/accesslog-multi-cel.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/accesslog-multi-cel.yaml
@@ -1,14 +1,18 @@
 name: "accesslog"
 accesslog:
-  celMatches:
-  - response.code >= 400
-  - request.url_path.contains('v1beta3')
+
   text:
   - path: "/dev/stdout"
+    celMatches:
+    - response.code >= 400
+    - request.url_path.contains('v1beta3')
     format: |
       [%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%" "%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"
   json:
   - path: "/dev/stdout"
+    celMatches:
+    - response.code >= 400
+    - request.url_path.contains('v1beta3')
     json:
       start_time: "%START_TIME%"
       method: "%REQ(:METHOD)%"
@@ -23,6 +27,9 @@ accesslog:
     resources:
       "cluster_name": "cluster1"
     authority: "otel-collector.default.svc.cluster.local"
+    celMatches:
+    - response.code >= 400
+    - request.url_path.contains('v1beta3')
     destination:
       name: "accesslog-0"
       settings:
diff --git a/internal/xds/translator/testdata/in/xds-ir/custom-filter-order.yaml b/internal/xds/translator/testdata/in/xds-ir/custom-filter-order.yaml
index 4650e1ea2..4971328e8 100644
--- a/internal/xds/translator/testdata/in/xds-ir/custom-filter-order.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/custom-filter-order.yaml
@@ -61,24 +61,25 @@ http:
           name: example2
           remoteJWKS:
             uri: http://two.example.com/jwt/public-key/jwks.json
-    wasm:
-    - config:
-        parameter1:
-          key1: value1
-          key2: value2
-        parameter2: value3
-      failOpen: false
-      httpWasmCode:
-        sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
-        servingURL: https://envoy-gateway:18002/42d30b4a4cc631415e6e48c02d244700da327201eb273f752cacf745715b31d9.wasm
-      name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/0
-      wasmName: wasm-filter-1
-    - config:
-        parameter1: value1
-        parameter2: value2
-      failOpen: false
-      httpWasmCode:
-        sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980
-        servingURL: https://envoy-gateway:18002/7abf116e5cd5a20389604a5ba0f3bd04fdf76f92181fe67506b42c2ee596d3fd.wasm
-      name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/1
-      wasmName: wasm-filter-2
+    envoyExtensions:
+      wasms:
+      - config:
+          parameter1:
+            key1: value1
+            key2: value2
+          parameter2: value3
+        failOpen: false
+        httpWasmCode:
+          sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
+          servingURL: https://envoy-gateway:18002/42d30b4a4cc631415e6e48c02d244700da327201eb273f752cacf745715b31d9.wasm
+        name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/0
+        wasmName: wasm-filter-1
+      - config:
+          parameter1: value1
+          parameter2: value2
+        failOpen: false
+        httpWasmCode:
+          sha256: a1efca12ea51069abb123bf9c77889fcc2a31cc5483fc14d115e44fdf07c7980
+          servingURL: https://envoy-gateway:18002/7abf116e5cd5a20389604a5ba0f3bd04fdf76f92181fe67506b42c2ee596d3fd.wasm
+        name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/1
+        wasmName: wasm-filter-2
diff --git a/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml b/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml
index 8209c2947..3fa4cd8bc 100644
--- a/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/ext-proc.yaml
@@ -18,30 +18,31 @@ http:
                   port: 8080
               protocol: HTTP
               weight: 1
-        extProc:
-          - name: envoyextensionpolicy/default/policy-for-route-2/extproc/0
-            failOpen: true
-            messageTimeout: 5s
-            requestHeaderProcessing: true
-            requestBodyProcessingMode: Buffered
-            responseBodyProcessingMode: Streamed
-            authority: grpc-backend-4.default:4000
-            destination:
-              name: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4
-              settings:
-                - protocol: GRPC
-                  weight: 1
-          - name: envoyextensionpolicy/default/policy-for-route-1/extproc/0
-            failOpen: true
-            messageTimeout: 5s
-            responseHeaderProcessing: true
-            requestBodyProcessingMode: BufferedPartial
-            authority: grpc-backend-2.default:8000
-            destination:
-              name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2
-              settings:
-                - protocol: GRPC
-                  weight: 1
+        envoyExtensions:
+          extProcs:
+            - name: envoyextensionpolicy/default/policy-for-route-2/extproc/0
+              failOpen: true
+              messageTimeout: 5s
+              requestHeaderProcessing: true
+              requestBodyProcessingMode: Buffered
+              responseBodyProcessingMode: Streamed
+              authority: grpc-backend-4.default:4000
+              destination:
+                name: envoyextensionpolicy/default/policy-for-route-2/0/grpc-backend-4
+                settings:
+                  - protocol: GRPC
+                    weight: 1
+            - name: envoyextensionpolicy/default/policy-for-route-1/extproc/0
+              failOpen: true
+              messageTimeout: 5s
+              responseHeaderProcessing: true
+              requestBodyProcessingMode: BufferedPartial
+              authority: grpc-backend-2.default:8000
+              destination:
+                name: envoyextensionpolicy/default/policy-for-route-1/0/grpc-backend-2
+                settings:
+                  - protocol: GRPC
+                    weight: 1
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
@@ -58,23 +59,24 @@ http:
                   port: 8080
               protocol: HTTP
               weight: 1
-        extProc:
-          - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/extproc/0
-            authority: grpc-backend-3.envoy-gateway:3000
-            destination:
-              name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3
-              settings:
-                - protocol: GRPC
-                  weight: 1
-          - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/extproc/0
-            failOpen: false
-            messageTimeout: 15s
-            authority: grpc-backend.envoy-gateway:9000
-            destination:
-              name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend
-              settings:
-                - protocol: GRPC
-                  weight: 1
+        envoyExtensions:
+          extProcs:
+            - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/extproc/0
+              authority: grpc-backend-3.envoy-gateway:3000
+              destination:
+                name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-2/0/grpc-backend-3
+                settings:
+                  - protocol: GRPC
+                    weight: 1
+            - name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/extproc/0
+              failOpen: false
+              messageTimeout: 15s
+              authority: grpc-backend.envoy-gateway:9000
+              destination:
+                name: envoyextensionpolicy/envoy-gateway/policy-for-gateway-1/0/grpc-backend
+                settings:
+                  - protocol: GRPC
+                    weight: 1
         hostname: gateway.envoyproxy.io
         isHTTP2: false
         name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io
diff --git a/internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml b/internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml
index 998318fdb..d2b754bf1 100644
--- a/internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/load-balancer.yaml
@@ -117,3 +117,18 @@ http:
       - endpoints:
         - host: "1.2.3.4"
           port: 50000
+  - name: "tenth-route"
+    hostname: "*"
+    traffic:
+      loadBalancer:
+        consistentHash:
+          cookie:
+            name: "test"
+            attributes:
+              foo: bar
+    destination:
+      name: "tenth-route-dest"
+      settings:
+      - endpoints:
+        - host: "1.2.3.4"
+          port: 50000
diff --git a/internal/xds/translator/testdata/in/xds-ir/wasm.yaml b/internal/xds/translator/testdata/in/xds-ir/wasm.yaml
index faa729eec..9afa2c97c 100644
--- a/internal/xds/translator/testdata/in/xds-ir/wasm.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/wasm.yaml
@@ -25,20 +25,21 @@ http:
       distinct: false
       name: ""
       prefix: /foo
-    wasm:
-    - config:
-        parameter1:
-          key1: value1
-        parameter2:
-          key2:
-            key3: value3
-      failOpen: true
-      httpWasmCode:
-        servingURL: https://envoy-gateway:18002/fe571e7b1ef5dc626ceb2c2c86782a134a92989a2643485238951696ae4334c3.wasm
-        originalDownloadingURL: https://www.test.com/wasm-filter-4.wasm
-        sha256: a1f0b78b8c1320690327800e3a5de10e7dbba7b6c752e702193a395a52c727b6
-      name: envoyextensionpolicy/default/policy-for-http-route/wasm/0
-      wasmName: wasm-filter-4
+    envoyExtensions:
+      wasms:
+      - config:
+          parameter1:
+            key1: value1
+          parameter2:
+            key2:
+              key3: value3
+        failOpen: true
+        httpWasmCode:
+          servingURL: https://envoy-gateway:18002/fe571e7b1ef5dc626ceb2c2c86782a134a92989a2643485238951696ae4334c3.wasm
+          originalDownloadingURL: https://www.test.com/wasm-filter-4.wasm
+          sha256: a1f0b78b8c1320690327800e3a5de10e7dbba7b6c752e702193a395a52c727b6
+        name: envoyextensionpolicy/default/policy-for-http-route/wasm/0
+        wasmName: wasm-filter-4
   - destination:
       name: httproute/default/httproute-2/rule/0
       settings:
@@ -55,35 +56,36 @@ http:
       distinct: false
       name: ""
       prefix: /bar
-    wasm:
-    - config:
-        parameter1:
-          key1: value1
-          key2: value2
-        parameter2: value3
-      failOpen: false
-      httpWasmCode:
-        servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
-        originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
-        sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
-      name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
-      wasmName: wasm-filter-1
-    - config:
-        parameter1: value1
-        parameter2: value2
-      failOpen: false
-      httpWasmCode:
-        servingURL: https://envoy-gateway:18002/7abf116e5cd5a20389604a5ba0f3bd04fdf76f92181fe67506b42c2ee596d3fd.wasm
-        originalDownloadingURL: oci://www.example.com/wasm-filter-2:v1.0.0
-        sha256: 314100af781b98a8ca175d5bf90a8bf76576e20a2f397a88223404edc6ebfd46
-      name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
-      wasmName: wasm-filter-2
-      rootID: my-root-id
-    - config: null
-      failOpen: false
-      httpWasmCode:
-        servingURL: https://envoy-gateway:18002/42d30b4a4cc631415e6e48c02d244700da327201eb273f752cacf745715b31d9.wasm
-        originalDownloadingURL: oci://www.example.com:8080/wasm-filter-3:latest
-        sha256: 2a19e4f337e5223d7287e7fccd933fb01905deaff804292e5257f8c681b82bee
-      name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/2
-      wasmName: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/2
+    envoyExtensions:
+      wasms:
+      - config:
+          parameter1:
+            key1: value1
+            key2: value2
+          parameter2: value3
+        failOpen: false
+        httpWasmCode:
+          servingURL: https://envoy-gateway:18002/5c90b9a82642ce00a7753923fabead306b9d9a54a7c0bd2463a1af3efcfb110b.wasm
+          originalDownloadingURL: https://www.example.com/wasm-filter-1.wasm
+          sha256: 746df05c8f3a0b07a46c0967cfbc5cbe5b9d48d0f79b6177eeedf8be6c8b34b5
+        name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/0
+        wasmName: wasm-filter-1
+      - config:
+          parameter1: value1
+          parameter2: value2
+        failOpen: false
+        httpWasmCode:
+          servingURL: https://envoy-gateway:18002/7abf116e5cd5a20389604a5ba0f3bd04fdf76f92181fe67506b42c2ee596d3fd.wasm
+          originalDownloadingURL: oci://www.example.com/wasm-filter-2:v1.0.0
+          sha256: 314100af781b98a8ca175d5bf90a8bf76576e20a2f397a88223404edc6ebfd46
+        name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/1
+        wasmName: wasm-filter-2
+        rootID: my-root-id
+      - config: null
+        failOpen: false
+        httpWasmCode:
+          servingURL: https://envoy-gateway:18002/42d30b4a4cc631415e6e48c02d244700da327201eb273f752cacf745715b31d9.wasm
+          originalDownloadingURL: oci://www.example.com:8080/wasm-filter-3:latest
+          sha256: 2a19e4f337e5223d7287e7fccd933fb01905deaff804292e5257f8c681b82bee
+        name: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/2
+        wasmName: envoyextensionpolicy/envoy-gateway/policy-for-gateway/wasm/2
diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.clusters.yaml
index cc88feed9..16792f24c 100644
--- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.clusters.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.clusters.yaml
@@ -157,3 +157,20 @@
   outlierDetection: {}
   perConnectionBufferLimitBytes: 32768
   type: EDS
+- circuitBreakers:
+    thresholds:
+    - maxRetries: 1024
+  commonLbConfig:
+    localityWeightedLbConfig: {}
+  connectTimeout: 10s
+  dnsLookupFamily: V4_ONLY
+  edsClusterConfig:
+    edsConfig:
+      ads: {}
+      resourceApiVersion: V3
+    serviceName: tenth-route-dest
+  lbPolicy: MAGLEV
+  name: tenth-route-dest
+  outlierDetection: {}
+  perConnectionBufferLimitBytes: 32768
+  type: EDS
diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.endpoints.yaml
index 31d553105..0295b1c71 100644
--- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.endpoints.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.endpoints.yaml
@@ -106,3 +106,15 @@
     loadBalancingWeight: 1
     locality:
       region: ninth-route-dest/backend/0
+- clusterName: tenth-route-dest
+  endpoints:
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 1.2.3.4
+            portValue: 50000
+      loadBalancingWeight: 1
+    loadBalancingWeight: 1
+    locality:
+      region: tenth-route-dest/backend/0
diff --git a/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml
index 8fcdb470f..07bf30df0 100644
--- a/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/load-balancer.routes.yaml
@@ -77,3 +77,16 @@
             name: test
         upgradeConfigs:
         - upgradeType: websocket
+    - match:
+        prefix: /
+      name: tenth-route
+      route:
+        cluster: tenth-route-dest
+        hashPolicy:
+        - cookie:
+            attributes:
+            - name: foo
+              value: bar
+            name: test
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/test/e2e/tests/utils.go b/test/e2e/tests/utils.go
index d620a9baa..c9ebe55f5 100644
--- a/test/e2e/tests/utils.go
+++ b/test/e2e/tests/utils.go
@@ -372,7 +372,7 @@ func RetrieveMetric(url string, name string, timeout time.Duration) (*dto.Metric
 		return mf, nil
 	}
 
-	return nil, fmt.Errorf("metric %s not found", name)
+	return nil, nil
 }
 
 func WaitForLoadBalancerAddress(t *testing.T, client client.Client, timeout time.Duration, nn types.NamespacedName) (string, error) {
@@ -411,6 +411,11 @@ func ALSLogCount(suite *suite.ConformanceTestSuite) (int, error) {
 		return -1, err
 	}
 
+	// metric not found or empty
+	if countMetric == nil {
+		return 0, nil
+	}
+
 	total := 0
 	for _, m := range countMetric.Metric {
 		if m.Counter != nil && m.Counter.Value != nil {