Repository: envoyproxy/gateway
Pull request #4363 (2024-09-29 12:20:09)

refactor: return 500 when BackendTLSPolicy translation fails
**What type of PR is this?**

What this PR does / why we need it:
- 500 for HTTP
- connection reset for TCP/UDP

Which issue(s) this PR fixes:
Fixes https://github.com/envoyproxy/gateway/issues/4087


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?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 `80.88235%` with `13 lines` in your changes missing coverage. Please review.
> Project coverage is 66.02%. Comparing base [(`b91f296`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/b91f296667badbf45f2fc6d7a342bde1f96ae082?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`c4d32d7`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/c4d32d7c12dd131b2cf6515d3ea815d432d0318d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

| [Files with missing lines](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?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/gatewayapi/route.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Froute.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9yb3V0ZS5nbw==) | 79.41% | [4 Missing and 3 partials :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |
| [internal/gatewayapi/filters.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Ffilters.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9maWx0ZXJzLmdv) | 72.72% | [2 Missing and 1 partial :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |
| [internal/gatewayapi/ext\_service.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Fext_service.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9leHRfc2VydmljZS5nbw==) | 50.00% | [1 Missing and 1 partial :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |
| [internal/gatewayapi/backendtlspolicy.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Fbackendtlspolicy.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9iYWNrZW5kdGxzcG9saWN5Lmdv) | 94.73% | [1 Missing :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?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    #4363      +/-   ##
==========================================
- Coverage   66.04%   66.02%   -0.03%     
==========================================
  Files         200      200              
  Lines       24052    24078      +26     
==========================================
+ Hits        15886    15897      +11     
- Misses       7036     7047      +11     
- Partials     1130     1134       +4     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/4363?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).

alexwo: /retest 
alexwo: /retes
alexwo: /retest
alexwo: /retest 
alexwo: /retest
alexwo: /retest
arkodg: @alexwo I dont see the conformance tests passing. I'm worried about the size of this change that not only applies to BTP but every error while translating route rules and backendRefs. For example if one out of the many backendRefs is invalid, only a portion of the requests should receive a 503
https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPBackendRef
alexwo: > @alexwo I dont see the conformance tests passing. I'm worried about the size of this change that not only applies to BTP but every error while translating route rules and backendRefs. For example if one out of the many backendRefs is invalid, only a portion of the requests should receive a 503 https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io%2fv1.HTTPBackendRef

@arkodg  indeed, the impact of the change is large, I can relate to it but hopefully all the tests in place get us covered.
The conformance tests pass, there was a lint issue and they did not start at all before.

If a portion of a backend ref configuration is invalid, say we are unable to process one the associated configurations, the question if routing to this backend ref should still happen?
alexwo: /retest
arkodg: > Now, if a part of the backend reference configuration is invalid — for example, if one of the associated configurations cannot be processed — the key question is: should routing to this backend reference still occur in such cases?

According to the spec, the answer is a portion of the requests (based on weights) should continue to be sent to the valid backendRef
alexwo: > > Now, if a part of the backend reference configuration is invalid — for example, if one of the associated configurations cannot be processed — the key question is: should routing to this backend reference still occur in such cases?
> 
> According to the spec, the answer is a portion of the requests (based on weights) should continue to be sent to the valid backendRef

We’re processing all backend routes and addressing only falty configured ones. This should ensures alignment with the spec, as valid backend routes will continue to function, while only those with invalid configurations will fail to render. 
( we process all routes for each backend and do not stop at error. )

alexwo: /retest
github-actions[bot]: This pull request has been automatically marked as stale because it has not had activity in the last 30 days. Please feel free to give a status update now, ping for review, when it's ready. Thank you for your contributions!
alexwo: /retest 
alexwo: /retest 
alexwo: /retest
alexwo: /retest 

Patch:
diff --git a/internal/gatewayapi/backendtlspolicy.go b/internal/gatewayapi/backendtlspolicy.go
index fbc9cafbf..0f99145f5 100644
--- a/internal/gatewayapi/backendtlspolicy.go
+++ b/internal/gatewayapi/backendtlspolicy.go
@@ -9,6 +9,7 @@ import (
 	"fmt"
 	"reflect"
 
+	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/utils/ptr"
 	gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
 	gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
@@ -20,8 +21,11 @@ import (
 	"github.com/envoyproxy/gateway/internal/ir"
 )
 
-func (t *Translator) applyBackendTLSSetting(backendRef gwapiv1.BackendObjectReference, backendNamespace string, parent gwapiv1a2.ParentReference, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy) *ir.TLSUpstreamConfig {
-	upstreamConfig, policy := t.processBackendTLSPolicy(backendRef, backendNamespace, parent, resources, envoyProxy)
+func (t *Translator) applyBackendTLSSetting(backendRef gwapiv1.BackendObjectReference, backendNamespace string, parent gwapiv1a2.ParentReference, resources *resource.Resources, envoyProxy *egv1a1.EnvoyProxy) (*ir.TLSUpstreamConfig, error) {
+	upstreamConfig, policy, err := t.processBackendTLSPolicy(backendRef, backendNamespace, parent, resources)
+	if err != nil {
+		return nil, err
+	}
 	return t.applyEnvoyProxyBackendTLSSetting(policy, upstreamConfig, resources, parent, envoyProxy)
 }
 
@@ -30,18 +34,13 @@ func (t *Translator) processBackendTLSPolicy(
 	backendNamespace string,
 	parent gwapiv1a2.ParentReference,
 	resources *resource.Resources,
-	envoyProxy *egv1a1.EnvoyProxy,
-) (*ir.TLSUpstreamConfig, *gwapiv1a3.BackendTLSPolicy) {
+) (*ir.TLSUpstreamConfig, *gwapiv1a3.BackendTLSPolicy, error) {
 	policy := getBackendTLSPolicy(resources.BackendTLSPolicies, backendRef, backendNamespace, resources)
 	if policy == nil {
-		return nil, nil
+		return nil, nil, nil
 	}
 
 	tlsBundle, err := getBackendTLSBundle(policy, resources)
-	if err == nil && tlsBundle == nil {
-		return nil, nil
-	}
-
 	ancestorRefs := getAncestorRefs(policy)
 	ancestorRefs = append(ancestorRefs, parent)
 
@@ -52,42 +51,16 @@ func (t *Translator) processBackendTLSPolicy(
 			policy.Generation,
 			status.Error2ConditionMsg(err),
 		)
-		return nil, nil
+		return nil, nil, err
 	}
 
 	status.SetAcceptedForPolicyAncestors(&policy.Status, ancestorRefs, t.GatewayControllerName)
-	// apply defaults as per envoyproxy
-	if envoyProxy != nil {
-		if envoyProxy.Spec.BackendTLS != nil {
-			if len(envoyProxy.Spec.BackendTLS.Ciphers) > 0 {
-				tlsBundle.Ciphers = envoyProxy.Spec.BackendTLS.Ciphers
-			}
-			if len(envoyProxy.Spec.BackendTLS.ECDHCurves) > 0 {
-				tlsBundle.ECDHCurves = envoyProxy.Spec.BackendTLS.ECDHCurves
-			}
-			if len(envoyProxy.Spec.BackendTLS.SignatureAlgorithms) > 0 {
-				tlsBundle.SignatureAlgorithms = envoyProxy.Spec.BackendTLS.SignatureAlgorithms
-			}
-			if envoyProxy.Spec.BackendTLS.MinVersion != nil {
-				tlsBundle.MinVersion = ptr.To(ir.TLSVersion(*envoyProxy.Spec.BackendTLS.MinVersion))
-			}
-			if envoyProxy.Spec.BackendTLS.MaxVersion != nil {
-				tlsBundle.MaxVersion = ptr.To(ir.TLSVersion(*envoyProxy.Spec.BackendTLS.MaxVersion))
-			}
-			if len(envoyProxy.Spec.BackendTLS.ALPNProtocols) > 0 {
-				tlsBundle.ALPNProtocols = make([]string, len(envoyProxy.Spec.BackendTLS.ALPNProtocols))
-				for i := range envoyProxy.Spec.BackendTLS.ALPNProtocols {
-					tlsBundle.ALPNProtocols[i] = string(envoyProxy.Spec.BackendTLS.ALPNProtocols[i])
-				}
-			}
-		}
-	}
-	return tlsBundle, policy
+	return tlsBundle, policy, nil
 }
 
-func (t *Translator) applyEnvoyProxyBackendTLSSetting(policy *gwapiv1a3.BackendTLSPolicy, tlsConfig *ir.TLSUpstreamConfig, resources *resource.Resources, parent gwapiv1a2.ParentReference, ep *egv1a1.EnvoyProxy) *ir.TLSUpstreamConfig {
+func (t *Translator) applyEnvoyProxyBackendTLSSetting(policy *gwapiv1a3.BackendTLSPolicy, tlsConfig *ir.TLSUpstreamConfig, resources *resource.Resources, parent gwapiv1a2.ParentReference, ep *egv1a1.EnvoyProxy) (*ir.TLSUpstreamConfig, error) {
 	if ep == nil || ep.Spec.BackendTLS == nil || tlsConfig == nil {
-		return tlsConfig
+		return tlsConfig, nil
 	}
 
 	if len(ep.Spec.BackendTLS.Ciphers) > 0 {
@@ -116,28 +89,41 @@ func (t *Translator) applyEnvoyProxyBackendTLSSetting(policy *gwapiv1a3.BackendT
 		ancestorRefs := []gwapiv1a2.ParentReference{
 			parent,
 		}
+		var err error
 		if ns != ep.Namespace {
+			err = fmt.Errorf("ClientCertificateRef Secret is not located in the same namespace as Envoyproxy. Secret namespace: %s does not match Envoyproxy namespace: %s", ns, ep.Namespace)
 			status.SetTranslationErrorForPolicyAncestors(&policy.Status,
 				ancestorRefs,
 				t.GatewayControllerName,
 				policy.Generation,
-				status.Error2ConditionMsg(fmt.Errorf("client authentication TLS secret is not located in the same namespace as Envoyproxy. Secret namespace: %s does not match Envoyproxy namespace: %s", ns, ep.Namespace)))
-			return tlsConfig
+				status.Error2ConditionMsg(err))
+			return tlsConfig, err
 		}
 		secret := resources.GetSecret(ns, string(ep.Spec.BackendTLS.ClientCertificateRef.Name))
 		if secret == nil {
+			err = fmt.Errorf(
+				"failed to locate TLS secret for client auth: %s specified in EnvoyProxy %s",
+				types.NamespacedName{
+					Namespace: ep.Namespace,
+					Name:      string(ep.Spec.BackendTLS.ClientCertificateRef.Name),
+				}.String(),
+				types.NamespacedName{
+					Namespace: ep.Namespace,
+					Name:      ep.Name,
+				}.String(),
+			)
 			status.SetTranslationErrorForPolicyAncestors(&policy.Status,
 				ancestorRefs,
 				t.GatewayControllerName,
 				policy.Generation,
-				status.Error2ConditionMsg(fmt.Errorf("failed to locate TLS secret for client auth: %s in namespace: %s", ep.Spec.BackendTLS.ClientCertificateRef.Name, ns)),
+				status.Error2ConditionMsg(err),
 			)
-			return tlsConfig
+			return tlsConfig, err
 		}
 		tlsConf := irTLSConfigs(secret)
 		tlsConfig.ClientCertificates = tlsConf.Certificates
 	}
-	return tlsConfig
+	return tlsConfig, nil
 }
 
 func backendTLSTargetMatched(policy gwapiv1a3.BackendTLSPolicy, target gwapiv1a2.LocalPolicyTargetReferenceWithSectionName, backendNamespace string) bool {
diff --git a/internal/gatewayapi/ext_service.go b/internal/gatewayapi/ext_service.go
index 39bd5aebe..b1111ffa0 100644
--- a/internal/gatewayapi/ext_service.go
+++ b/internal/gatewayapi/ext_service.go
@@ -110,7 +110,8 @@ func (t *Translator) processExtServiceDestination(
 			"mixed endpointslice address type for the same backendRef is not supported")
 	}
 
-	backendTLS = t.applyBackendTLSSetting(
+	var err error
+	backendTLS, err = t.applyBackendTLSSetting(
 		backendRef.BackendObjectReference,
 		backendNamespace,
 		// Gateway is not the appropriate parent reference here because the owner
@@ -126,6 +127,9 @@ func (t *Translator) processExtServiceDestination(
 		resources,
 		envoyProxy,
 	)
+	if err != nil {
+		return nil, err
+	}
 
 	ds.TLS = backendTLS
 
diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go
index 68bf84b33..7e1b5f040 100644
--- a/internal/gatewayapi/filters.go
+++ b/internal/gatewayapi/filters.go
@@ -31,8 +31,7 @@ type HTTPFiltersTranslator interface {
 	processRedirectFilter(redirect *gwapiv1.HTTPRequestRedirectFilter, filterContext *HTTPFiltersContext)
 	processRequestHeaderModifierFilter(headerModifier *gwapiv1.HTTPHeaderFilter, filterContext *HTTPFiltersContext)
 	processResponseHeaderModifierFilter(headerModifier *gwapiv1.HTTPHeaderFilter, filterContext *HTTPFiltersContext)
-	processRequestMirrorFilter(filterIdx int, mirror *gwapiv1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, resources *resource.Resources)
-	processExtensionRefHTTPFilter(extRef *gwapiv1.LocalObjectReference, filterContext *HTTPFiltersContext, resources *resource.Resources)
+	processRequestMirrorFilter(filterIdx int, mirror *gwapiv1.HTTPRequestMirrorFilter, filterContext *HTTPFiltersContext, resources *resource.Resources) error
 	processUnsupportedHTTPFilter(filterType string, filterContext *HTTPFiltersContext)
 }
 
@@ -69,13 +68,14 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext,
 	filters []gwapiv1.HTTPRouteFilter,
 	ruleIdx int,
 	resources *resource.Resources,
-) *HTTPFiltersContext {
+) (*HTTPFiltersContext, error) {
 	httpFiltersContext := &HTTPFiltersContext{
 		ParentRef:    parentRef,
 		Route:        route,
 		RuleIdx:      ruleIdx,
 		HTTPFilterIR: &HTTPFilterIR{},
 	}
+	var err error
 	for i := range filters {
 		filter := filters[i]
 		// If an invalid filter type has been configured then skip processing any more filters
@@ -97,7 +97,7 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext,
 		case gwapiv1.HTTPRouteFilterResponseHeaderModifier:
 			t.processResponseHeaderModifierFilter(filter.ResponseHeaderModifier, httpFiltersContext)
 		case gwapiv1.HTTPRouteFilterRequestMirror:
-			t.processRequestMirrorFilter(i, filter.RequestMirror, httpFiltersContext, resources)
+			err = t.processRequestMirrorFilter(i, filter.RequestMirror, httpFiltersContext, resources)
 		case gwapiv1.HTTPRouteFilterExtensionRef:
 			t.processExtensionRefHTTPFilter(filter.ExtensionRef, httpFiltersContext, resources)
 		default:
@@ -105,7 +105,7 @@ func (t *Translator) ProcessHTTPFilters(parentRef *RouteParentContext,
 		}
 	}
 
-	return httpFiltersContext
+	return httpFiltersContext, err
 }
 
 // ProcessGRPCFilters translates gateway api grpc filters to IRs.
@@ -113,13 +113,14 @@ func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext,
 	route RouteContext,
 	filters []gwapiv1.GRPCRouteFilter,
 	resources *resource.Resources,
-) *HTTPFiltersContext {
+) (*HTTPFiltersContext, error) {
 	httpFiltersContext := &HTTPFiltersContext{
 		ParentRef: parentRef,
 		Route:     route,
 
 		HTTPFilterIR: &HTTPFilterIR{},
 	}
+
 	for i := range filters {
 		filter := filters[i]
 		// If an invalid filter type has been configured then skip processing any more filters
@@ -137,7 +138,10 @@ func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext,
 		case gwapiv1.GRPCRouteFilterResponseHeaderModifier:
 			t.processResponseHeaderModifierFilter(filter.ResponseHeaderModifier, httpFiltersContext)
 		case gwapiv1.GRPCRouteFilterRequestMirror:
-			t.processRequestMirrorFilter(i, filter.RequestMirror, httpFiltersContext, resources)
+			err := t.processRequestMirrorFilter(i, filter.RequestMirror, httpFiltersContext, resources)
+			if err != nil {
+				return nil, err
+			}
 		case gwapiv1.GRPCRouteFilterExtensionRef:
 			t.processExtensionRefHTTPFilter(filter.ExtensionRef, httpFiltersContext, resources)
 		default:
@@ -145,7 +149,7 @@ func (t *Translator) ProcessGRPCFilters(parentRef *RouteParentContext,
 		}
 	}
 
-	return httpFiltersContext
+	return httpFiltersContext, nil
 }
 
 // Checks if the context and the rewrite both contain a core gw-api HTTP URL rewrite
@@ -968,10 +972,10 @@ func (t *Translator) processRequestMirrorFilter(
 	mirrorFilter *gwapiv1.HTTPRequestMirrorFilter,
 	filterContext *HTTPFiltersContext,
 	resources *resource.Resources,
-) {
+) error {
 	// Make sure the config actually exists
 	if mirrorFilter == nil {
-		return
+		return nil
 	}
 
 	mirrorBackend := mirrorFilter.BackendRef
@@ -988,18 +992,23 @@ func (t *Translator) processRequestMirrorFilter(
 	// This sets the status on the HTTPRoute, should the usage be changed so that the status message reflects that the backendRef is from the filter?
 	filterNs := filterContext.Route.GetNamespace()
 	serviceNamespace := NamespaceDerefOr(mirrorBackend.Namespace, filterNs)
-	if !t.validateBackendRef(mirrorBackendRef, filterContext.ParentRef, filterContext.Route,
-		resources, serviceNamespace, resource.KindHTTPRoute) {
-		return
+	err := t.validateBackendRef(mirrorBackendRef, filterContext.ParentRef, filterContext.Route,
+		resources, serviceNamespace, resource.KindHTTPRoute)
+	if err != nil {
+		return err
 	}
 
-	ds := t.processDestination(mirrorBackendRef, filterContext.ParentRef, filterContext.Route, resources)
+	ds, err := t.processDestination(mirrorBackendRef, filterContext.ParentRef, filterContext.Route, resources)
+	if err != nil {
+		return err
+	}
 
 	newMirror := &ir.RouteDestination{
 		Name:     fmt.Sprintf("%s-mirror-%d", irRouteDestinationName(filterContext.Route, filterContext.RuleIdx), filterIdx),
 		Settings: []*ir.DestinationSetting{ds},
 	}
 	filterContext.Mirrors = append(filterContext.Mirrors, newMirror)
+	return nil
 }
 
 func (t *Translator) processUnresolvedHTTPFilter(errMsg string, filterContext *HTTPFiltersContext) {
diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go
index 0fd60b0c5..544bb85d6 100644
--- a/internal/gatewayapi/route.go
+++ b/internal/gatewayapi/route.go
@@ -184,8 +184,10 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
 
 	// compute matches, filters, backends
 	for ruleIdx, rule := range httpRoute.Spec.Rules {
-		httpFiltersContext := t.ProcessHTTPFilters(parentRef, httpRoute, rule.Filters, ruleIdx, resources)
-
+		httpFiltersContext, err := t.ProcessHTTPFilters(parentRef, httpRoute, rule.Filters, ruleIdx, resources)
+		if err != nil {
+			return nil, err
+		}
 		// A rule is matched if any one of its matches
 		// is satisfied (i.e. a logical "OR"), so generate
 		// a unique Xds IR HTTPRoute per match.
@@ -197,16 +199,23 @@ func (t *Translator) processHTTPRouteRules(httpRoute *HTTPRouteContext, parentRe
 		dstAddrTypeMap := make(map[ir.DestinationAddressType]int)
 
 		for _, backendRef := range rule.BackendRefs {
-			ds := t.processDestination(backendRef, parentRef, httpRoute, resources)
-
+			ds, err := t.processDestination(backendRef, parentRef, httpRoute, resources)
 			if !t.IsEnvoyServiceRouting(envoyProxy) && ds != nil && len(ds.Endpoints) > 0 && ds.AddressType != nil {
 				dstAddrTypeMap[*ds.AddressType]++
 			}
-			if ds == nil {
-				continue
-			}
 
 			for _, route := range ruleRoutes {
+				// disable associated routes to a backend ref in case some of its config was invalid
+				if err != nil {
+					route.DirectResponse = &ir.CustomResponse{
+						StatusCode: ptr.To(uint32(500)),
+					}
+					continue
+				}
+
+				if ds == nil {
+					continue
+				}
 				// If the route already has a direct response or redirect configured, then it was from a filter so skip
 				// processing any destinations for this route.
 				if route.DirectResponse != nil || route.Redirect != nil {
@@ -536,8 +545,10 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
 
 	// compute matches, filters, backends
 	for ruleIdx, rule := range grpcRoute.Spec.Rules {
-		httpFiltersContext := t.ProcessGRPCFilters(parentRef, grpcRoute, rule.Filters, resources)
-
+		httpFiltersContext, err := t.ProcessGRPCFilters(parentRef, grpcRoute, rule.Filters, resources)
+		if err != nil {
+			return nil, err
+		}
 		// A rule is matched if any one of its matches
 		// is satisfied (i.e. a logical "OR"), so generate
 		// a unique Xds IR HTTPRoute per match.
@@ -547,7 +558,7 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
 		}
 
 		for _, backendRef := range rule.BackendRefs {
-			ds := t.processDestination(backendRef, parentRef, grpcRoute, resources)
+			ds, err := t.processDestination(backendRef, parentRef, grpcRoute, resources)
 			if ds == nil {
 				continue
 			}
@@ -559,6 +570,13 @@ func (t *Translator) processGRPCRouteRules(grpcRoute *GRPCRouteContext, parentRe
 					continue
 				}
 
+				//  disable associated routes to a backend ref in case some of its config was invalid
+				if err != nil {
+					route.DirectResponse = &ir.CustomResponse{
+						StatusCode: ptr.To(uint32(500)),
+					}
+				}
+
 				if route.Destination == nil {
 					route.Destination = &ir.RouteDestination{
 						Name: irRouteDestinationName(grpcRoute, ruleIdx),
@@ -831,7 +849,8 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour
 		// compute backends
 		for _, rule := range tlsRoute.Spec.Rules {
 			for _, backendRef := range rule.BackendRefs {
-				ds := t.processDestination(backendRef, parentRef, tlsRoute, resources)
+				// not yet handled, requires to align with the conformance test - TLSRouteInvalidReferenceGrant.
+				ds, _ := t.processDestination(backendRef, parentRef, tlsRoute, resources)
 				if ds != nil {
 					destSettings = append(destSettings, ds)
 				}
@@ -971,11 +990,20 @@ func (t *Translator) processUDPRouteParentRefs(udpRoute *UDPRouteContext, resour
 		}
 
 		for _, backendRef := range udpRoute.Spec.Rules[0].BackendRefs {
-			ds := t.processDestination(backendRef, parentRef, udpRoute, resources)
-			if ds == nil {
+			ds, err := t.processDestination(backendRef, parentRef, udpRoute, resources)
+			// skip adding the route and provide the reason via route status.
+			if err != nil {
+				routeStatus := GetRouteStatus(udpRoute)
+				status.SetRouteStatusCondition(routeStatus,
+					parentRef.routeParentStatusIdx,
+					udpRoute.GetGeneration(),
+					gwapiv1.RouteConditionAccepted,
+					metav1.ConditionFalse,
+					"Failed to process the settings associated with the UDP route.",
+					err.Error(),
+				)
 				continue
 			}
-
 			destSettings = append(destSettings, ds)
 		}
 
@@ -1104,11 +1132,20 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
 		}
 
 		for _, backendRef := range tcpRoute.Spec.Rules[0].BackendRefs {
-			ds := t.processDestination(backendRef, parentRef, tcpRoute, resources)
-			if ds == nil {
+			ds, err := t.processDestination(backendRef, parentRef, tcpRoute, resources)
+			// skip adding the route and provide the reason via route status.
+			if err != nil {
+				routeStatus := GetRouteStatus(tcpRoute)
+				status.SetRouteStatusCondition(routeStatus,
+					parentRef.routeParentStatusIdx,
+					tcpRoute.GetGeneration(),
+					gwapiv1.RouteConditionAccepted,
+					metav1.ConditionFalse,
+					"Failed to process the settings associated with the TCP route.",
+					err.Error(),
+				)
 				continue
 			}
-
 			destSettings = append(destSettings, ds)
 		}
 
@@ -1197,12 +1234,12 @@ func (t *Translator) processTCPRouteParentRefs(tcpRoute *TCPRouteContext, resour
 	}
 }
 
-// processDestination takes a backendRef and translates it into destination setting or sets error statuses and
-// returns the weight for the backend so that 500 error responses can be returned for invalid backends in
-// the same proportion as the backend would have otherwise received
+// processDestination translates a backendRef into a destination settings.
+// If an error occurs during this conversion, an error is returned, and the associated routes are expected to become inactive.
+// This will result in a direct 500 response for HTTP-based requests.
 func (t *Translator) processDestination(backendRefContext BackendRefContext,
 	parentRef *RouteParentContext, route RouteContext, resources *resource.Resources,
-) (ds *ir.DestinationSetting) {
+) (ds *ir.DestinationSetting, err error) {
 	routeType := GetRouteType(route)
 	weight := uint32(1)
 	backendRef := GetBackendRef(backendRefContext)
@@ -1211,14 +1248,17 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext,
 	}
 
 	backendNamespace := NamespaceDerefOr(backendRef.Namespace, route.GetNamespace())
-	if !t.validateBackendRef(backendRefContext, parentRef, route, resources, backendNamespace, routeType) {
-		// return with empty endpoint means the backend is invalid
-		return &ir.DestinationSetting{Weight: &weight}
+	err = t.validateBackendRef(backendRefContext, parentRef, route, resources, backendNamespace, routeType)
+	{
+		// return with empty endpoint means the backend is invalid and an error to fail the associated route.
+		if err != nil {
+			return nil, err
+		}
 	}
 
 	// Skip processing backends with 0 weight
 	if weight == 0 {
-		return nil
+		return nil, nil
 	}
 
 	var envoyProxy *egv1a1.EnvoyProxy
@@ -1266,7 +1306,7 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext,
 
 	case resource.KindService:
 		ds = t.processServiceDestinationSetting(backendRef.BackendObjectReference, backendNamespace, protocol, resources, envoyProxy)
-		ds.TLS = t.applyBackendTLSSetting(
+		ds.TLS, err = t.applyBackendTLSSetting(
 			backendRef.BackendObjectReference,
 			backendNamespace,
 			gwapiv1a2.ParentReference{
@@ -1280,12 +1320,17 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext,
 			resources,
 			envoyProxy,
 		)
-		ds.Filters = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources)
+		if err != nil {
+			return nil, err
+		}
+		ds.Filters, err = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources)
+		if err != nil {
+			return nil, err
+		}
 		ds.IPFamily = getServiceIPFamily(resources.GetService(backendNamespace, string(backendRef.Name)))
 	case egv1a1.KindBackend:
 		ds = t.processBackendDestinationSetting(backendRef.BackendObjectReference, backendNamespace, resources)
-
-		ds.TLS = t.applyBackendTLSSetting(
+		ds.TLS, err = t.applyBackendTLSSetting(
 			backendRef.BackendObjectReference,
 			backendNamespace,
 			gwapiv1a2.ParentReference{
@@ -1299,8 +1344,13 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext,
 			resources,
 			envoyProxy,
 		)
-
-		ds.Filters = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources)
+		if err != nil {
+			return nil, err
+		}
+		ds.Filters, err = t.processDestinationFilters(routeType, backendRefContext, parentRef, route, resources)
+		if err != nil {
+			return nil, err
+		}
 	}
 
 	if err := validateDestinationSettings(ds, t.IsEnvoyServiceRouting(envoyProxy), backendRef.Kind); err != nil {
@@ -1312,10 +1362,11 @@ func (t *Translator) processDestination(backendRefContext BackendRefContext,
 			metav1.ConditionFalse,
 			gwapiv1.RouteReasonResolvedRefs,
 			err.Error())
+		return nil, err
 	}
 
 	ds.Weight = &weight
-	return ds
+	return ds, nil
 }
 
 func validateDestinationSettings(destinationSettings *ir.DestinationSetting, endpointRoutingDisabled bool, kind *gwapiv1.Kind) error {
@@ -1400,25 +1451,29 @@ func getBackendFilters(routeType gwapiv1.Kind, backendRefContext BackendRefConte
 	return nil
 }
 
-func (t *Translator) processDestinationFilters(routeType gwapiv1.Kind, backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *resource.Resources) *ir.DestinationFilters {
+func (t *Translator) processDestinationFilters(routeType gwapiv1.Kind, backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext, resources *resource.Resources) (*ir.DestinationFilters, error) {
 	backendFilters := getBackendFilters(routeType, backendRefContext)
 	if backendFilters == nil {
-		return nil
+		return nil, nil
 	}
 
 	var httpFiltersContext *HTTPFiltersContext
 	var destFilters ir.DestinationFilters
 
+	var err error
 	switch filters := backendFilters.(type) {
 	case []gwapiv1.HTTPRouteFilter:
-		httpFiltersContext = t.ProcessHTTPFilters(parentRef, route, filters, 0, resources)
+		httpFiltersContext, err = t.ProcessHTTPFilters(parentRef, route, filters, 0, resources)
 
 	case []gwapiv1.GRPCRouteFilter:
-		httpFiltersContext = t.ProcessGRPCFilters(parentRef, route, filters, resources)
+		httpFiltersContext, err = t.ProcessGRPCFilters(parentRef, route, filters, resources)
+		if err != nil {
+			return &destFilters, err
+		}
 	}
 	applyHTTPFiltersContextToDestinationFilters(httpFiltersContext, &destFilters)
 
-	return &destFilters
+	return &destFilters, err
 }
 
 func applyHTTPFiltersContextToDestinationFilters(httpFiltersContext *HTTPFiltersContext, destFilters *ir.DestinationFilters) {
diff --git a/internal/gatewayapi/validate.go b/internal/gatewayapi/validate.go
index fb5d49957..37a007444 100644
--- a/internal/gatewayapi/validate.go
+++ b/internal/gatewayapi/validate.go
@@ -26,28 +26,30 @@ import (
 
 func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, parentRef *RouteParentContext, route RouteContext,
 	resources *resource.Resources, backendNamespace string, routeKind gwapiv1.Kind,
-) bool {
+) error {
 	backendRef := GetBackendRef(backendRefContext)
 
-	if !t.validateBackendRefFilters(backendRefContext, parentRef, route, routeKind) {
-		return false
+	if err := t.validateBackendRefFilters(backendRefContext, parentRef, route, routeKind); err != nil {
+		return fmt.Errorf("error validating backend filters: %w", err)
 	}
-	if !t.validateBackendRefGroup(backendRef, parentRef, route) {
-		return false
+	if err := t.validateBackendRefGroup(backendRef, parentRef, route); err != nil {
+		return fmt.Errorf("error validating backend group: %w", err)
 	}
-	if !t.validateBackendRefKind(backendRef, parentRef, route) {
-		return false
+	if err := t.validateBackendRefKind(backendRef, parentRef, route); err != nil {
+		return fmt.Errorf("error validating backend kind: %w", err)
 	}
-	if !t.validateBackendNamespace(backendRef, parentRef, route, resources, routeKind) {
-		return false
+	if err := t.validateBackendNamespace(backendRef, parentRef, route, resources, routeKind); err != nil {
+		return fmt.Errorf("error validating backend namespace: %w", err)
 	}
-	if !t.validateBackendPort(backendRef, parentRef, route) {
-		return false
+	if err := t.validateBackendPort(backendRef, parentRef, route); err != nil {
+		return fmt.Errorf("error validating backend port: %w", err)
 	}
+
 	protocol := corev1.ProtocolTCP
 	if routeKind == resource.KindUDPRoute {
 		protocol = corev1.ProtocolUDP
 	}
+
 	backendRefKind := KindDerefOr(backendRef.Kind, resource.KindService)
 	switch backendRefKind {
 	case resource.KindService:
@@ -61,21 +63,21 @@ func (t *Translator) validateBackendRef(backendRefContext BackendRefContext, par
 				gwapiv1.RouteReasonBackendNotFound,
 				err.Error(),
 			)
-			return false
+			return fmt.Errorf("backend service validation failed: %w", err)
 		}
 	case resource.KindServiceImport:
-		if !t.validateBackendServiceImport(backendRef, parentRef, resources, backendNamespace, route, protocol) {
-			return false
+		if err := t.validateBackendServiceImport(backendRef, parentRef, resources, backendNamespace, route, protocol); err != nil {
+			return fmt.Errorf("backend service import validation failed: %w", err)
 		}
 	case egv1a1.KindBackend:
-		if !t.validateBackendRefBackend(backendRef, parentRef, resources, backendNamespace, route, routeKind) {
-			return false
+		if err := t.validateBackendRefBackend(backendRef, parentRef, resources, backendNamespace, route, routeKind); err != nil {
+			return fmt.Errorf("backend reference validation failed: %w", err)
 		}
 	}
-	return true
+	return nil
 }
 
-func (t *Translator) validateBackendRefGroup(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) bool {
+func (t *Translator) validateBackendRefGroup(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) error {
 	if backendRef.Group != nil && *backendRef.Group != "" && *backendRef.Group != GroupMultiClusterService && *backendRef.Group != egv1a1.GroupName {
 		routeStatus := GetRouteStatus(route)
 		status.SetRouteStatusCondition(routeStatus,
@@ -86,12 +88,12 @@ func (t *Translator) validateBackendRefGroup(backendRef *gwapiv1a2.BackendRef, p
 			gwapiv1.RouteReasonInvalidKind,
 			fmt.Sprintf("Group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string), %s and %s are supported", GroupMultiClusterService, egv1a1.GroupName),
 		)
-		return false
+		return fmt.Errorf("unsupported backend reference group: %s", *backendRef.Group)
 	}
-	return true
+	return nil
 }
 
-func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) bool {
+func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) error {
 	if backendRef.Kind != nil && *backendRef.Kind != resource.KindService && *backendRef.Kind != resource.KindServiceImport && *backendRef.Kind != egv1a1.KindBackend {
 		routeStatus := GetRouteStatus(route)
 		status.SetRouteStatusCondition(routeStatus,
@@ -102,12 +104,12 @@ func (t *Translator) validateBackendRefKind(backendRef *gwapiv1a2.BackendRef, pa
 			gwapiv1.RouteReasonInvalidKind,
 			"Kind is invalid, only Service, MCS ServiceImport and Envoy Gateway Backend are supported",
 		)
-		return false
+		return fmt.Errorf("unsupported backend reference kind: %s", *backendRef.Kind)
 	}
-	return true
+	return nil
 }
 
-func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, parentRef *RouteParentContext, route RouteContext, routeKind gwapiv1.Kind) bool {
+func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, parentRef *RouteParentContext, route RouteContext, routeKind gwapiv1.Kind) error {
 	filters := GetFilters(backendRef)
 	var unsupportedFilters bool
 
@@ -125,7 +127,7 @@ func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, par
 			}
 		}
 	default:
-		return true
+		return nil
 	}
 
 	if unsupportedFilters {
@@ -138,15 +140,15 @@ func (t *Translator) validateBackendRefFilters(backendRef BackendRefContext, par
 			"UnsupportedRefValue",
 			"Specific filter is not supported within BackendRef, only RequestHeaderModifier and ResponseHeaderModifier are supported",
 		)
-		return false
+		return errors.New("unsupported filter type in backend reference")
 	}
 
-	return true
+	return nil
 }
 
 func (t *Translator) validateBackendNamespace(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext,
 	resources *resource.Resources, routeKind gwapiv1.Kind,
-) bool {
+) error {
 	if backendRef.Namespace != nil && string(*backendRef.Namespace) != "" && string(*backendRef.Namespace) != route.GetNamespace() {
 		if !t.validateCrossNamespaceRef(
 			crossNamespaceFrom{
@@ -171,16 +173,15 @@ func (t *Translator) validateBackendNamespace(backendRef *gwapiv1a2.BackendRef,
 				gwapiv1.RouteReasonRefNotPermitted,
 				fmt.Sprintf("Backend ref to %s %s/%s not permitted by any ReferenceGrant.", KindDerefOr(backendRef.Kind, resource.KindService), *backendRef.Namespace, backendRef.Name),
 			)
-			return false
+			return fmt.Errorf("cross-namespace reference not permitted for backend: %s", backendRef.Name)
 		}
 	}
-	return true
+	return nil
 }
 
-func (t *Translator) validateBackendPort(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) bool {
-	// Envoy Gateway Backends do not require a port in the backend ref
+func (t *Translator) validateBackendPort(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, route RouteContext) error {
 	if backendRef != nil && backendRef.Kind != nil && string(*backendRef.Kind) == egv1a1.KindBackend {
-		return true
+		return nil
 	}
 	if backendRef.Port == nil {
 		routeStatus := GetRouteStatus(route)
@@ -192,9 +193,9 @@ func (t *Translator) validateBackendPort(backendRef *gwapiv1a2.BackendRef, paren
 			"PortNotSpecified",
 			"A valid port number corresponding to a port on the Service must be specified",
 		)
-		return false
+		return errors.New("port number not specified for backend reference")
 	}
-	return true
+	return nil
 }
 
 func validateBackendService(backendRef gwapiv1a2.BackendObjectReference, resources *resource.Resources,
@@ -226,7 +227,7 @@ func validateBackendService(backendRef gwapiv1a2.BackendObjectReference, resourc
 
 func (t *Translator) validateBackendServiceImport(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, resources *resource.Resources,
 	serviceImportNamespace string, route RouteContext, protocol corev1.Protocol,
-) bool {
+) error {
 	serviceImport := resources.GetServiceImport(serviceImportNamespace, string(backendRef.Name))
 	if serviceImport == nil {
 		routeStatus := GetRouteStatus(route)
@@ -239,8 +240,9 @@ func (t *Translator) validateBackendServiceImport(backendRef *gwapiv1a2.BackendR
 			fmt.Sprintf("ServiceImport %s/%s not found", NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()),
 				string(backendRef.Name)),
 		)
-		return false
+		return fmt.Errorf("service import %s/%s not found", serviceImportNamespace, backendRef.Name)
 	}
+
 	var portFound bool
 	for _, port := range serviceImport.Spec.Ports {
 		portProtocol := port.Protocol
@@ -264,15 +266,15 @@ func (t *Translator) validateBackendServiceImport(backendRef *gwapiv1a2.BackendR
 			fmt.Sprintf(string(protocol)+" Port %d not found on ServiceImport %s/%s", *backendRef.Port, serviceImportNamespace,
 				string(backendRef.Name)),
 		)
-		return false
+		return fmt.Errorf("%s port %d not found on service import %s/%s", string(protocol), *backendRef.Port, serviceImportNamespace, backendRef.Name)
 	}
-	return true
+
+	return nil
 }
 
 func (t *Translator) validateBackendRefBackend(backendRef *gwapiv1a2.BackendRef, parentRef *RouteParentContext, resources *resource.Resources,
 	backendNamespace string, route RouteContext, kind gwapiv1.Kind,
-) bool {
-	// TODO: support additional route kinds
+) error {
 	routeStatus := GetRouteStatus(route)
 
 	if !t.BackendEnabled {
@@ -285,7 +287,7 @@ func (t *Translator) validateBackendRefBackend(backendRef *gwapiv1a2.BackendRef,
 			fmt.Sprintf("Resource %s/%s of type Backend cannot be used since Backend is disabled in Envoy Gateway configuration",
 				NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()), string(backendRef.Name)),
 		)
-		return false
+		return errors.New("backend is disabled in Envoy Gateway configuration")
 	}
 
 	if kind != resource.KindHTTPRoute && kind != resource.KindTLSRoute {
@@ -298,7 +300,7 @@ func (t *Translator) validateBackendRefBackend(backendRef *gwapiv1a2.BackendRef,
 			fmt.Sprintf("Resource %s/%s of type Backend is not supported for %s routes", NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()),
 				string(backendRef.Name), kind),
 		)
-		return false
+		return fmt.Errorf("backend is not supported for route kind: %s", kind)
 	}
 
 	backend := resources.GetBackend(backendNamespace, string(backendRef.Name))
@@ -312,7 +314,7 @@ func (t *Translator) validateBackendRefBackend(backendRef *gwapiv1a2.BackendRef,
 			fmt.Sprintf("Backend %s/%s not found", NamespaceDerefOr(backendRef.Namespace, route.GetNamespace()),
 				string(backendRef.Name)),
 		)
-		return false
+		return fmt.Errorf("backend %s/%s not found", backendNamespace, backendRef.Name)
 	}
 
 	if err := validateBackend(backend); err != nil {
@@ -325,7 +327,7 @@ func (t *Translator) validateBackendRefBackend(backendRef *gwapiv1a2.BackendRef,
 			fmt.Sprintf("Invalid Backend reference to Backend %s/%s found", backendNamespace,
 				string(backendRef.Name)),
 		)
-		return false
+		return fmt.Errorf("invalid backend reference: %w", err)
 	}
 
 	for _, bep := range backend.Spec.Endpoints {
@@ -339,11 +341,11 @@ func (t *Translator) validateBackendRefBackend(backendRef *gwapiv1a2.BackendRef,
 				fmt.Sprintf("Unix domain socket found in Backend %s/%s is not supported for xRoute backendRefs", backendNamespace,
 					string(backendRef.Name)),
 			)
-			return false
+			return errors.New("unix domain sockets are not supported in backend references")
 		}
 	}
 
-	return true
+	return nil
 }
 
 func (t *Translator) validateListenerConditions(listener *ListenerContext) (isReady bool) {


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 49d35c607..d942bf363 100644
--- a/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml
+++ b/internal/gatewayapi/testdata/backend-invalid-feature-disabled.out.yaml
@@ -168,11 +168,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/backendtlspolicy-invalid-ca.out.yaml b/internal/gatewayapi/testdata/backendtlspolicy-invalid-ca.out.yaml
index 20e749d0e..c4436b7f6 100644
--- a/internal/gatewayapi/testdata/backendtlspolicy-invalid-ca.out.yaml
+++ b/internal/gatewayapi/testdata/backendtlspolicy-invalid-ca.out.yaml
@@ -147,15 +147,8 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-btls/rule/0
-          settings:
-          - addressType: IP
-            endpoints:
-            - host: 10.244.0.11
-              port: 8080
-            protocol: HTTP
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml
index 1a054712d..7c63ff375 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-status-conditions.out.yaml
@@ -555,11 +555,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
@@ -593,11 +589,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: grpcroute/envoy-gateway/grpcroute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         headerMatches:
         - distinct: false
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-distinct-invert.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-distinct-invert.out.yaml
index 4ea1623c8..d4c68adcb 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-distinct-invert.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-ratelimit-invalid-distinct-invert.out.yaml
@@ -149,11 +149,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: grpcroute/default/grpcroute/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: true
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-targetrefs.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-targetrefs.out.yaml
index ea546413a..72646d946 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-targetrefs.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-timeout-targetrefs.out.yaml
@@ -252,11 +252,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: grpcroute/envoy-gateway/grpcroute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: true
@@ -292,11 +288,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml b/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml
index 8561d9300..f7816b6f7 100644
--- a/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml
+++ b/internal/gatewayapi/testdata/clienttrafficpolicy-http10.out.yaml
@@ -520,11 +520,7 @@ xdsIR:
         mergeSlashes: true
       port: 8082
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: route.example.com
         isHTTP2: false
@@ -553,11 +549,7 @@ xdsIR:
         mergeSlashes: true
       port: 8083
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: route.example.com
         isHTTP2: false
@@ -570,11 +562,7 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /
-      - destination:
-          name: httproute/envoy-gateway/httproute-2/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: route2.example.com
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/custom-filter-order.out.yaml b/internal/gatewayapi/testdata/custom-filter-order.out.yaml
index a8c4413a3..9e2aa5400 100644
--- a/internal/gatewayapi/testdata/custom-filter-order.out.yaml
+++ b/internal/gatewayapi/testdata/custom-filter-order.out.yaml
@@ -240,11 +240,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         envoyExtensions:
           wasms:
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml
index f4cc57f95..51aa2de1c 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-status-conditions.out.yaml
@@ -555,11 +555,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         envoyExtensions: {}
         hostname: '*'
@@ -593,11 +589,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: grpcroute/envoy-gateway/grpcroute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         envoyExtensions: {}
         headerMatches:
diff --git a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml
index 8c65fb9cf..f61cabdcf 100644
--- a/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml
+++ b/internal/gatewayapi/testdata/envoyextensionpolicy-with-wasm-targetrefs.out.yaml
@@ -222,11 +222,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         envoyExtensions:
           wasms:
@@ -263,11 +259,7 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /foo
-      - destination:
-          name: httproute/envoy-gateway/httproute-2/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         envoyExtensions:
           wasms:
diff --git a/internal/gatewayapi/testdata/envoyproxy-accesslog-types.out.yaml b/internal/gatewayapi/testdata/envoyproxy-accesslog-types.out.yaml
index 9c2c0d1cf..ee6c126ab 100644
--- a/internal/gatewayapi/testdata/envoyproxy-accesslog-types.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-accesslog-types.out.yaml
@@ -441,11 +441,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml
index 7e86495fc..306302e68 100644
--- a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid-ns.out.yaml
@@ -20,7 +20,7 @@ backendTLSPolicies:
         namespace: envoy-gateway
       conditions:
       - lastTransitionTime: null
-        message: 'Client authentication TLS secret is not located in the same namespace
+        message: 'ClientCertificateRef Secret is not located in the same namespace
           as Envoyproxy. Secret namespace: envoy-gateway-user-ns does not match Envoyproxy
           namespace: envoy-gateway-system.'
         reason: Invalid
@@ -209,9 +209,11 @@ tcpRoutes:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: Route is accepted
-        reason: Accepted
-        status: "True"
+        message: 'ClientCertificateRef Secret is not located in the same namespace
+          as Envoyproxy. Secret namespace: envoy-gateway-user-ns does not match Envoyproxy
+          namespace: envoy-gateway-system'
+        reason: Failed to process the settings associated with the TCP route.
+        status: "False"
         type: Accepted
       - lastTransitionTime: null
         message: Resolved all the Object references for the Route
@@ -242,32 +244,8 @@ xdsIR:
         mergeSlashes: true
       port: 10443
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-tls/rule/0
-          settings:
-          - addressType: IP
-            endpoints:
-            - host: 10.244.0.11
-              port: 443
-            protocol: HTTP
-            tls:
-              alpnProtocols:
-              - HTTP/1.1
-              - HTTP/2
-              ciphers:
-              - ECDHE-RSA-AES128-GCM-SHA256
-              - ECDHE-ECDSA-AES256-GCM-SHA384
-              ecdhCurves:
-              - ECDHE-RSA-AES128-GCM-SHA256
-              - ECDHE-ECDSA-AES256-GCM-SHA384
-              maxVersion: tls1.3
-              minVersion: tls1.2
-              signatureAlgorithms:
-              - RSA-PSS-RSAE-SHA256
-              - ECDSA-SECP256R1-SHA256
-              sni: example.com
-              useSystemTrustStore: true
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
@@ -285,41 +263,6 @@ xdsIR:
     - address: 0.0.0.0
       name: envoy-gateway/gateway-tls/
       port: 10445
-      routes:
-      - destination:
-          name: tcproute/envoy-gateway/envoy-gateway/rule/-1
-          settings:
-          - addressType: IP
-            endpoints:
-            - host: 10.244.0.11
-              port: 443
-            protocol: TCP
-            tls:
-              alpnProtocols:
-              - HTTP/1.1
-              - HTTP/2
-              ciphers:
-              - ECDHE-RSA-AES128-GCM-SHA256
-              - ECDHE-ECDSA-AES256-GCM-SHA384
-              ecdhCurves:
-              - ECDHE-RSA-AES128-GCM-SHA256
-              - ECDHE-ECDSA-AES256-GCM-SHA384
-              maxVersion: tls1.3
-              minVersion: tls1.2
-              signatureAlgorithms:
-              - RSA-PSS-RSAE-SHA256
-              - ECDSA-SECP256R1-SHA256
-              sni: example.com
-              useSystemTrustStore: true
-            weight: 1
-        name: tcproute/envoy-gateway/envoy-gateway
-        tls:
-          terminate:
-            alpnProtocols: []
-            certificates:
-            - name: envoy-gateway/default-cert
-              privateKey: '[redacted]'
-              serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKRENDQWd5Z0F3SUJBZ0lVU3JTYktMZjBiTEVHb2dXeC9nQ3cyR0N0dnhFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0V6RVJNQThHQTFVRUF3d0lWR1Z6ZENCSmJtTXdIaGNOTWpRd01qSTVNRGt6TURFd1doY05NelF3TWpJMgpNRGt6TURFd1dqQVRNUkV3RHdZRFZRUUREQWhVWlhOMElFbHVZekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBSzFKempQSWlXZzNxb0hTckFkZGtlSmphTVA5aXlNVGkvQlBvOWNKUG9SRThaaTcKV2FwVXJYTC85QTlyK2pITXlHSVpOWk5kY1o1Y1kyWHYwTFA4WnhWeTJsazArM3d0WXpIbnBHWUdWdHlxMnRldApEaEZzaVBsODJZUmpDMG16V2E0UU16NFNYekZITmdJRHBSZGhmcm92bXNldVdHUUU4cFY0VWQ5VUsvU0tpbE1PCnF0QjVKaXJMUDJWczVUMW9XaWNXTFF2ZmJHd3Y3c0ZEZHI5YkcwWHRTUXAxN0hTZ281MFNERTUrQmpTbXB0RncKMVZjS0xscWFoTVhCRERpb3Jnd2hJaEdHS3BFU2VNMFA3YkZoVm1rTTNhc2gyeFNUQnVGVUJEbEU0Sk9haHp3cwpEWHJ1cFVoRGRTMWhkYzJmUHJqaEZBbEpmV0VZWjZCbFpqeXNpVlVDQXdFQUFhTndNRzR3SFFZRFZSME9CQllFCkZCUXVmSzFMaWJ1Vm05VHMvVmpCeDhMM3VpTmVNQjhHQTFVZEl3UVlNQmFBRkJRdWZLMUxpYnVWbTlUcy9WakIKeDhMM3VpTmVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdHd1lEVlIwUkJCUXdFb0lCS29JTktpNWxlR0Z0Y0d4bApMbU52YlRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWZQUzQxYWdldldNVjNaWHQwQ09GRzN1WWZQRlhuVnc2ClA0MXA5TzZHa2RZc3VxRnZQZVR5eUgyL2RBSUtLd1N6TS9wdGhnOEtuOExabG1KeUZObkExc3RKeG41WGRiVjEKcFBxajhVdllDQnp5ak1JcW1SeW9peUxpUWxib2hNYTBVZEVCS2NIL1BkTEU5SzhUR0pyWmdvR1hxcTFXbWl0RAozdmNQalNlUEtFaVVKVlM5bENoeVNzMEtZNUIraFVRRDBKajZucEZENFprMHhxZHhoMHJXdWVDcXE3dmpxRVl6CnBqNFB3cnVmbjFQQlRtZnhNdVYvVUpWNWViaWtldVpQMzVrV3pMUjdaV0FMN3d1RGRXcC82bzR5azNRTGFuRFEKQ3dnQ0ZjWCtzcyswVnl1TTNZZXJUT1VVOFFWSkp4NFVaQU5aeDYrNDNwZEpaT2NudFBaNENBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
       tls:
         alpnProtocols: []
         certificates:
diff --git a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml
index 868620d8d..2078ceeb7 100644
--- a/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml
+++ b/internal/gatewayapi/testdata/envoyproxy-tls-settings-invalid.out.yaml
@@ -20,8 +20,8 @@ backendTLSPolicies:
         namespace: envoy-gateway
       conditions:
       - lastTransitionTime: null
-        message: 'Failed to locate TLS secret for client auth: client-auth-not-found
-          in namespace: envoy-gateway-system.'
+        message: 'Failed to locate TLS secret for client auth: envoy-gateway-system/client-auth-not-found
+          specified in EnvoyProxy envoy-gateway-system/test.'
         reason: Invalid
         status: "False"
         type: Accepted
@@ -208,9 +208,10 @@ tcpRoutes:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: Route is accepted
-        reason: Accepted
-        status: "True"
+        message: 'failed to locate TLS secret for client auth: envoy-gateway-system/client-auth-not-found
+          specified in EnvoyProxy envoy-gateway-system/test'
+        reason: Failed to process the settings associated with the TCP route.
+        status: "False"
         type: Accepted
       - lastTransitionTime: null
         message: Resolved all the Object references for the Route
@@ -241,32 +242,8 @@ xdsIR:
         mergeSlashes: true
       port: 10443
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-tls/rule/0
-          settings:
-          - addressType: IP
-            endpoints:
-            - host: 10.244.0.11
-              port: 443
-            protocol: HTTP
-            tls:
-              alpnProtocols:
-              - HTTP/1.1
-              - HTTP/2
-              ciphers:
-              - ECDHE-RSA-AES128-GCM-SHA256
-              - ECDHE-ECDSA-AES256-GCM-SHA384
-              ecdhCurves:
-              - ECDHE-RSA-AES128-GCM-SHA256
-              - ECDHE-ECDSA-AES256-GCM-SHA384
-              maxVersion: tls1.3
-              minVersion: tls1.2
-              signatureAlgorithms:
-              - RSA-PSS-RSAE-SHA256
-              - ECDSA-SECP256R1-SHA256
-              sni: example.com
-              useSystemTrustStore: true
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
@@ -284,41 +261,6 @@ xdsIR:
     - address: 0.0.0.0
       name: envoy-gateway/gateway-tls/
       port: 10445
-      routes:
-      - destination:
-          name: tcproute/envoy-gateway/envoy-gateway/rule/-1
-          settings:
-          - addressType: IP
-            endpoints:
-            - host: 10.244.0.11
-              port: 443
-            protocol: TCP
-            tls:
-              alpnProtocols:
-              - HTTP/1.1
-              - HTTP/2
-              ciphers:
-              - ECDHE-RSA-AES128-GCM-SHA256
-              - ECDHE-ECDSA-AES256-GCM-SHA384
-              ecdhCurves:
-              - ECDHE-RSA-AES128-GCM-SHA256
-              - ECDHE-ECDSA-AES256-GCM-SHA384
-              maxVersion: tls1.3
-              minVersion: tls1.2
-              signatureAlgorithms:
-              - RSA-PSS-RSAE-SHA256
-              - ECDSA-SECP256R1-SHA256
-              sni: example.com
-              useSystemTrustStore: true
-            weight: 1
-        name: tcproute/envoy-gateway/envoy-gateway
-        tls:
-          terminate:
-            alpnProtocols: []
-            certificates:
-            - name: envoy-gateway/default-cert
-              privateKey: '[redacted]'
-              serverCertificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKRENDQWd5Z0F3SUJBZ0lVU3JTYktMZjBiTEVHb2dXeC9nQ3cyR0N0dnhFd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0V6RVJNQThHQTFVRUF3d0lWR1Z6ZENCSmJtTXdIaGNOTWpRd01qSTVNRGt6TURFd1doY05NelF3TWpJMgpNRGt6TURFd1dqQVRNUkV3RHdZRFZRUUREQWhVWlhOMElFbHVZekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBSzFKempQSWlXZzNxb0hTckFkZGtlSmphTVA5aXlNVGkvQlBvOWNKUG9SRThaaTcKV2FwVXJYTC85QTlyK2pITXlHSVpOWk5kY1o1Y1kyWHYwTFA4WnhWeTJsazArM3d0WXpIbnBHWUdWdHlxMnRldApEaEZzaVBsODJZUmpDMG16V2E0UU16NFNYekZITmdJRHBSZGhmcm92bXNldVdHUUU4cFY0VWQ5VUsvU0tpbE1PCnF0QjVKaXJMUDJWczVUMW9XaWNXTFF2ZmJHd3Y3c0ZEZHI5YkcwWHRTUXAxN0hTZ281MFNERTUrQmpTbXB0RncKMVZjS0xscWFoTVhCRERpb3Jnd2hJaEdHS3BFU2VNMFA3YkZoVm1rTTNhc2gyeFNUQnVGVUJEbEU0Sk9haHp3cwpEWHJ1cFVoRGRTMWhkYzJmUHJqaEZBbEpmV0VZWjZCbFpqeXNpVlVDQXdFQUFhTndNRzR3SFFZRFZSME9CQllFCkZCUXVmSzFMaWJ1Vm05VHMvVmpCeDhMM3VpTmVNQjhHQTFVZEl3UVlNQmFBRkJRdWZLMUxpYnVWbTlUcy9WakIKeDhMM3VpTmVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdHd1lEVlIwUkJCUXdFb0lCS29JTktpNWxlR0Z0Y0d4bApMbU52YlRBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQWZQUzQxYWdldldNVjNaWHQwQ09GRzN1WWZQRlhuVnc2ClA0MXA5TzZHa2RZc3VxRnZQZVR5eUgyL2RBSUtLd1N6TS9wdGhnOEtuOExabG1KeUZObkExc3RKeG41WGRiVjEKcFBxajhVdllDQnp5ak1JcW1SeW9peUxpUWxib2hNYTBVZEVCS2NIL1BkTEU5SzhUR0pyWmdvR1hxcTFXbWl0RAozdmNQalNlUEtFaVVKVlM5bENoeVNzMEtZNUIraFVRRDBKajZucEZENFprMHhxZHhoMHJXdWVDcXE3dmpxRVl6CnBqNFB3cnVmbjFQQlRtZnhNdVYvVUpWNWViaWtldVpQMzVrV3pMUjdaV0FMN3d1RGRXcC82bzR5azNRTGFuRFEKQ3dnQ0ZjWCtzcyswVnl1TTNZZXJUT1VVOFFWSkp4NFVaQU5aeDYrNDNwZEpaT2NudFBaNENBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
       tls:
         alpnProtocols: []
         certificates:
diff --git a/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml
index cb47542a1..ce4166089 100644
--- a/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml
@@ -187,11 +187,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: bar.com
         isHTTP2: false
@@ -219,11 +215,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-2/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*.example.com'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml
index 866ca1e86..64e9d93ea 100644
--- a/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-listener-with-tcproute-with-mismatch-port-protocol.out.yaml
@@ -72,9 +72,10 @@ tcpRoutes:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: Route is accepted
-        reason: Accepted
-        status: "True"
+        message: 'backend service validation failed: TCP Port 8081 not found on service
+          default/service-1'
+        reason: Failed to process the settings associated with the TCP route.
+        status: "False"
         type: Accepted
       - lastTransitionTime: null
         message: TCP Port 8081 not found on service default/service-1
@@ -94,9 +95,3 @@ xdsIR:
     - address: 0.0.0.0
       name: envoy-gateway/gateway-1/tcp
       port: 10162
-      routes:
-      - destination:
-          name: tcproute/default/tcproute-1/rule/-1
-          settings:
-          - weight: 1
-        name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml
index 03cf19502..2e62a910d 100644
--- a/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml
+++ b/internal/gatewayapi/testdata/gateway-with-listener-with-udproute-with-mismatch-port-protocol.out.yaml
@@ -72,9 +72,10 @@ udpRoutes:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: Route is accepted
-        reason: Accepted
-        status: "True"
+        message: 'backend service validation failed: UDP Port 8080 not found on service
+          default/service-1'
+        reason: Failed to process the settings associated with the UDP route.
+        status: "False"
         type: Accepted
       - lastTransitionTime: null
         message: UDP Port 8080 not found on service default/service-1
@@ -94,9 +95,3 @@ xdsIR:
     - address: 0.0.0.0
       name: envoy-gateway/gateway-1/udp
       port: 10162
-      route:
-        destination:
-          name: udproute/default/udproute-1/rule/-1
-          settings:
-          - weight: 1
-        name: udproute/default/udproute-1
diff --git a/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml
index 8981d87b0..1d7cb3074 100644
--- a/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml
+++ b/internal/gatewayapi/testdata/grpcroute-with-backend.out.yaml
@@ -139,11 +139,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: grpcroute/default/grpcroute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: true
@@ -157,11 +153,7 @@ xdsIR:
           distinct: false
           name: ""
           safeRegex: /com.[A-Z]+/[A-Za-z_][A-Za-z_0-9]*
-      - destination:
-          name: grpcroute/default/grpcroute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: true
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml
index 80b6f6627..64b578f98 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref-mixed-address-type.out.yaml
@@ -274,11 +274,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
@@ -291,16 +287,8 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /1
-      - destination:
-          name: httproute/default/httproute-3/rule/0
-          settings:
-          - addressType: Mixed
-            endpoints:
-            - host: primary.foo.com
-              port: 3000
-            - host: 1.1.1.1
-              port: 3001
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
@@ -312,16 +300,8 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /3
-      - destination:
-          name: httproute/default/httproute-2/rule/0
-          settings:
-          - addressType: Mixed
-            endpoints:
-            - host: primary.foo.com
-              port: 3000
-            - host: 1.1.1.1
-              port: 3001
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml
index cdbbe7880..c252ac4d7 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-backend-backendref.out.yaml
@@ -357,11 +357,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
@@ -412,11 +408,7 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /2
-      - destination:
-          name: httproute/default/httproute-4/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
@@ -429,11 +421,7 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /4
-      - destination:
-          name: httproute/default/httproute-5/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml
index 3b5ddfa62..86255af66 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-diff-address-type.out.yaml
@@ -296,20 +296,8 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-          - addressType: IP
-            endpoints:
-            - host: 1.1.1.1
-              port: 3001
-            weight: 1
-          - addressType: FQDN
-            endpoints:
-            - host: primary.foo.com
-              port: 3000
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
@@ -321,15 +309,8 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /1
-      - destination:
-          name: httproute/default/httproute-2/rule/0
-          settings:
-          - weight: 1
-          - addressType: IP
-            endpoints:
-            - host: 1.1.1.1
-              port: 3001
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
@@ -365,15 +346,8 @@ xdsIR:
           distinct: false
           name: ""
           prefix: /3
-      - destination:
-          name: httproute/default/httproute-3/rule/0
-          settings:
-          - weight: 1
-          - addressType: FQDN
-            endpoints:
-            - host: primary.foo.com
-              port: 3000
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml
index 5a413ae46..c16b8a064 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-multiple-backend-backendrefs-same-address-type.out.yaml
@@ -305,12 +305,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml
index 38c70c4a8..9cf885504 100644
--- a/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-attaching-to-listener-with-serviceimport-backendref-mixed-address-type.out.yaml
@@ -115,17 +115,8 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - addressType: Mixed
-            endpoints:
-            - host: 1.2.3.4
-              port: 8080
-            - host: foo.bar
-              port: 8081
-            protocol: HTTP
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-bad-port.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-bad-port.out.yaml
index 2ca033356..57e337fd1 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-bad-port.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-bad-port.out.yaml
@@ -112,11 +112,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml
index e7c2869de..c6090f5c1 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-group.out.yaml
@@ -116,11 +116,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml
index a1c5683d2..984dc0c98 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-invalid-kind.out.yaml
@@ -114,11 +114,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-port.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-port.out.yaml
index ed62f94f2..4274a5f86 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-port.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-port.out.yaml
@@ -112,11 +112,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.import.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.import.out.yaml
index 794a5d87c..06a770648 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.import.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.import.out.yaml
@@ -114,11 +114,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.out.yaml
index 18019d56e..ae96ef5ed 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-no-service.out.yaml
@@ -112,11 +112,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml
index f9ee3bb21..df79cfc2e 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-backend-ref-unsupported-filter.out.yaml
@@ -119,11 +119,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-with-invalid-backendref-in-other-namespace.out.yaml b/internal/gatewayapi/testdata/httproute-with-invalid-backendref-in-other-namespace.out.yaml
index 3500d3be9..c22e21c89 100644
--- a/internal/gatewayapi/testdata/httproute-with-invalid-backendref-in-other-namespace.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-invalid-backendref-in-other-namespace.out.yaml
@@ -113,11 +113,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml
index 50105a1e0..af0ed8f79 100644
--- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-no-port.out.yaml
@@ -71,9 +71,10 @@ httpRoutes:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: Route is accepted
-        reason: Accepted
-        status: "True"
+        message: 'Error validating backend port: port number not specified for backend
+          reference.'
+        reason: UnsupportedValue
+        status: "False"
         type: Accepted
       - lastTransitionTime: null
         message: A valid port number corresponding to a port on the Service must be
@@ -122,24 +123,3 @@ xdsIR:
         escapedSlashesAction: UnescapeAndRedirect
         mergeSlashes: true
       port: 10080
-      routes:
-      - destination:
-          name: httproute/default/httproute-1/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-1
-          namespace: default
-        name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
-        pathMatch:
-          distinct: false
-          name: ""
-          prefix: /
diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml
index c0c193e03..85ff5860d 100644
--- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-service-not-found.out.yaml
@@ -72,9 +72,10 @@ httpRoutes:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: Route is accepted
-        reason: Accepted
-        status: "True"
+        message: 'Backend service validation failed: Service default/service-unknown
+          not found.'
+        reason: UnsupportedValue
+        status: "False"
         type: Accepted
       - lastTransitionTime: null
         message: Service default/service-unknown not found
@@ -122,24 +123,3 @@ xdsIR:
         escapedSlashesAction: UnescapeAndRedirect
         mergeSlashes: true
       port: 10080
-      routes:
-      - destination:
-          name: httproute/default/httproute-1/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-1
-          namespace: default
-        name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
-        pathMatch:
-          distinct: false
-          name: ""
-          prefix: /
diff --git a/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml b/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml
index ff9f5d272..37776a693 100644
--- a/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-some-invalid-backend-refs-no-service.out.yaml
@@ -116,17 +116,8 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/default/httproute-1/rule/0
-          settings:
-          - weight: 1
-          - weight: 1
-          - addressType: IP
-            endpoints:
-            - host: 7.7.7.7
-              port: 8080
-            protocol: HTTP
-            weight: 1
+      - directResponse:
+          statusCode: 500
         hostname: '*'
         isHTTP2: false
         metadata:
diff --git a/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml b/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml
index 607330a82..3dc5888bb 100644
--- a/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-status-conditions.out.yaml
@@ -421,11 +421,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: false
@@ -459,11 +455,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: grpcroute/envoy-gateway/grpcroute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         headerMatches:
         - distinct: false
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-cors-targetrefs.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-cors-targetrefs.out.yaml
index 789da0519..5438cf7dc 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-cors-targetrefs.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-cors-targetrefs.out.yaml
@@ -354,11 +354,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: grpcroute/envoy-gateway/grpcroute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: '*'
         isHTTP2: true
@@ -409,11 +405,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-1/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
@@ -446,11 +438,7 @@ xdsIR:
         mergeSlashes: true
       port: 10080
       routes:
-      - destination:
-          name: httproute/envoy-gateway/httproute-2/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: gateway.envoyproxy.io
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
index ccdb24583..d5326219c 100644
--- a/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
+++ b/internal/gatewayapi/testdata/securitypolicy-with-extauth-backend.out.yaml
@@ -510,11 +510,7 @@ xdsIR:
             - header3
             - header4
             name: securitypolicy/default/policy-for-http-route-3--grpc-backendref
-      - destination:
-          name: httproute/default/httproute-4/rule/0
-          settings:
-          - weight: 1
-        directResponse:
+      - directResponse:
           statusCode: 500
         hostname: www.qux.com
         isHTTP2: false
diff --git a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
index 29a124844..951d4c752 100644
--- a/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
+++ b/internal/gatewayapi/testdata/tcproute-with-backend.out.yaml
@@ -92,9 +92,10 @@ tcpRoutes:
     parents:
     - conditions:
       - lastTransitionTime: null
-        message: Route is accepted
-        reason: Accepted
-        status: "True"
+        message: 'backend reference validation failed: backend is not supported for
+          route kind: TCPRoute'
+        reason: Failed to process the settings associated with the TCP route.
+        status: "False"
         type: Accepted
       - lastTransitionTime: null
         message: Resource default/backend-ip of type Backend is not supported for
@@ -115,9 +116,3 @@ xdsIR:
     - address: 0.0.0.0
       name: envoy-gateway/gateway-1/tcp
       port: 10090
-      routes:
-      - destination:
-          name: tcproute/default/tcproute-1/rule/-1
-          settings:
-          - weight: 1
-        name: tcproute/default/tcproute-1
diff --git a/internal/gatewayapi/testdata/tlsroute-invalid-reference-grant.in.yaml b/internal/gatewayapi/testdata/tlsroute-invalid-reference-grant.in.yaml
new file mode 100644
index 000000000..99d362580
--- /dev/null
+++ b/internal/gatewayapi/testdata/tlsroute-invalid-reference-grant.in.yaml
@@ -0,0 +1,139 @@
+referenceGrants:
+  - apiVersion: gateway.networking.k8s.io/v1beta1
+    kind: ReferenceGrant
+    metadata:
+      name: reference-grant-wrong-namespace
+      namespace: gateway-conformance-infra
+    spec:
+      from:
+        - group: gateway.networking.k8s.io
+          kind: TLSRoute
+          namespace: gateway-conformance-infra
+      to:
+        - group: ""
+          kind: Service
+          name: tls-backend
+
+  - apiVersion: gateway.networking.k8s.io/v1beta1
+    kind: ReferenceGrant
+    metadata:
+      name: reference-grant-wrong-from-group
+      namespace: gateway-conformance-app-backend
+    spec:
+      from:
+        - group: not-the-group-youre-looking-for
+          kind: TLSRoute
+          namespace: gateway-conformance-infra
+      to:
+        - group: ""
+          kind: Service
+          name: tls-backend
+  - apiVersion: gateway.networking.k8s.io/v1beta1
+    kind: ReferenceGrant
+    metadata:
+      name: reference-grant-wrong-from-kind
+      namespace: gateway-conformance-app-backend
+    spec:
+      from:
+        - group: gateway.networking.k8s.io
+          kind: Gateway
+          namespace: gateway-conformance-infra
+      to:
+        - group: ""
+          kind: Service
+          name: tls-backend
+  - apiVersion: gateway.networking.k8s.io/v1beta1
+    kind: ReferenceGrant
+    metadata:
+      name: reference-grant-wrong-from-namespace
+      namespace: gateway-conformance-app-backend
+    spec:
+      from:
+        - group: gateway.networking.k8s.io
+          kind: TLSRoute
+          namespace: not-the-namespace-youre-looking-for
+      to:
+        - group: ""
+          kind: Service
+          name: tls-backend
+
+  - apiVersion: gateway.networking.k8s.io/v1beta1
+    kind: ReferenceGrant
+    metadata:
+      name: reference-grant-wrong-to-group
+      namespace: gateway-conformance-app-backend
+    spec:
+      from:
+        - group: gateway.networking.k8s.io
+          kind: TLSRoute
+          namespace: gateway-conformance-infra
+      to:
+        - group: not-the-group-youre-looking-for
+          kind: Service
+          name: tls-backend
+
+  - apiVersion: gateway.networking.k8s.io/v1beta1
+    kind: ReferenceGrant
+    metadata:
+      name: reference-grant-wrong-to-kind
+      namespace: gateway-conformance-app-backend
+    spec:
+      from:
+        - group: gateway.networking.k8s.io
+          kind: TLSRoute
+          namespace: gateway-conformance-infra
+      to:
+        - group: ""
+          kind: Secret
+          name: tls-backend
+
+  - apiVersion: gateway.networking.k8s.io/v1beta1
+    kind: ReferenceGrant
+    metadata:
+      name: reference-grant-wrong-to-name
+      namespace: gateway-conformance-app-backend
+    spec:
+      from:
+        - group: gateway.networking.k8s.io
+          kind: TLSRoute
+          namespace: gateway-conformance-infra
+      to:
+        - group: ""
+          kind: Service
+          name: not-the-service-youre-looking-for
+tlsRoutes:
+  - apiVersion: gateway.networking.k8s.io/v1alpha2
+    kind: TLSRoute
+    metadata:
+      name: gateway-conformance-infra-test
+      namespace: gateway-conformance-infra
+    spec:
+      parentRefs:
+        - name: gateway-tlsroute-referencegrant
+      hostnames:
+        - abc.example.com
+      rules:
+        - backendRefs:
+            - name: tls-backend
+              namespace: gateway-conformance-app-backend
+              port: 443
+gateways:
+  - apiVersion: gateway.networking.k8s.io/v1beta1
+    kind: Gateway
+    metadata:
+      name: gateway-tlsroute-referencegrant
+      namespace: gateway-conformance-infra
+    spec:
+      gatewayClassName: envoy-gateway-class
+      listeners:
+        - name: https
+          port: 443
+          protocol: TLS
+          hostname: "*.example.com"
+          allowedRoutes:
+            namespaces:
+              from: Same
+            kinds:
+              - kind: TLSRoute
+          tls:
+            mode: Passthrough
diff --git a/internal/gatewayapi/testdata/tlsroute-invalid-reference-grant.out.yaml b/internal/gatewayapi/testdata/tlsroute-invalid-reference-grant.out.yaml
new file mode 100644
index 000000000..833bcd489
--- /dev/null
+++ b/internal/gatewayapi/testdata/tlsroute-invalid-reference-grant.out.yaml
@@ -0,0 +1,102 @@
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1beta1
+  kind: Gateway
+  metadata:
+    creationTimestamp: null
+    name: gateway-tlsroute-referencegrant
+    namespace: gateway-conformance-infra
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - allowedRoutes:
+        kinds:
+        - kind: TLSRoute
+        namespaces:
+          from: Same
+      hostname: '*.example.com'
+      name: https
+      port: 443
+      protocol: TLS
+      tls:
+        mode: Passthrough
+  status:
+    listeners:
+    - attachedRoutes: 0
+      conditions:
+      - lastTransitionTime: null
+        message: Sending translated listener configuration to the data plane
+        reason: Programmed
+        status: "True"
+        type: Programmed
+      - lastTransitionTime: null
+        message: Listener has been successfully translated
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Listener references have been resolved
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      name: https
+      supportedKinds:
+      - kind: TLSRoute
+infraIR:
+  gateway-conformance-infra/gateway-tlsroute-referencegrant:
+    proxy:
+      listeners:
+      - address: null
+        name: gateway-conformance-infra/gateway-tlsroute-referencegrant/https
+        ports:
+        - containerPort: 10443
+          name: tls-443
+          protocol: TLS
+          servicePort: 443
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-tlsroute-referencegrant
+          gateway.envoyproxy.io/owning-gateway-namespace: gateway-conformance-infra
+      name: gateway-conformance-infra/gateway-tlsroute-referencegrant
+tlsRoutes:
+- apiVersion: gateway.networking.k8s.io/v1alpha2
+  kind: TLSRoute
+  metadata:
+    creationTimestamp: null
+    name: gateway-conformance-infra-test
+    namespace: gateway-conformance-infra
+  spec:
+    hostnames:
+    - abc.example.com
+    parentRefs:
+    - name: gateway-tlsroute-referencegrant
+    rules:
+    - backendRefs:
+      - name: tls-backend
+        namespace: gateway-conformance-app-backend
+        port: 443
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: No listeners included by this parent ref allowed this attachment.
+        reason: NotAllowedByListeners
+        status: "False"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Backend ref to Service gateway-conformance-app-backend/tls-backend
+          not permitted by any ReferenceGrant.
+        reason: RefNotPermitted
+        status: "False"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-tlsroute-referencegrant
+xdsIR:
+  gateway-conformance-infra/gateway-tlsroute-referencegrant:
+    accessLog:
+      text:
+      - path: /dev/stdout
+    tcp:
+    - address: 0.0.0.0
+      name: gateway-conformance-infra/gateway-tlsroute-referencegrant/https
+      port: 10443