Repository: istio/istio (go)

Issue:
Large HTTPDirectResponse breaks gateways
### Bug Description

Much like #42510 , a large `HTTPDirectResponse` bigger than 4096 bytes breaks gateways.  This results in an error like

```
warn	ads	ADS:RDS: ACK ERROR istio-ingressgateway-internal-844db46d-4vjlr.istio-ingressgateway-internal-4695 Internal:response body size is 15747 bytes; maximum is 4096
```



### Version

```prose
istioctl version
client version: 1.17.2
control plane version: 1.17.2
data plane version: 1.13.3 (1 proxies), 1.16.2 (42 proxies), 1.17.1 (92 proxies), 1.17.2 (45 proxies)

istioctl version --short=false | grep istio-ingressgateway-internal
data plane version: version.ProxyInfo{ID:"istio-ingressgateway-internal-844db46d-4vjlr.istio-ingressgateway-internal", IstioVersion:"1.17.2"}
data plane version: version.ProxyInfo{ID:"istio-ingressgateway-internal-844db46d-krfs8.istio-ingressgateway-internal", IstioVersion:"1.17.2"}
data plane version: version.ProxyInfo{ID:"istio-ingressgateway-internal-844db46d-ql9dr.istio-ingressgateway-internal", IstioVersion:"1.17.2"}

kubectl version
kubectl version --short.  Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"25", GitVersion:"v1.25.2", GitCommit:"5835544ca568b757a8ecae5c153f317e5736700e", GitTreeState:"clean", BuildDate:"2022-09-21T14:33:49Z", GoVersion:"go1.19.1", Compiler:"gc", Platform:"darwin/amd64"}
Kustomize Version: v4.5.7
Server Version: version.Info{Major:"1", Minor:"24", GitVersion:"v1.24.9", GitCommit:"57fbbcc2804848b95cad5519f5ec9d6355430db9", GitTreeState:"clean", BuildDate:"2023-02-08T17:22:38Z", GoVersion:"go1.18.9", Compiler:"gc", Platform:"linux/amd64"}
```


### Additional Information

_No response_

### Affected product area

- [ ] Ambient
- [ ] Docs
- [ ] Installation
- [X] Networking
- [ ] Performance and Scalability
- [ ] Extensions and Telemetry
- [ ] Security
- [ ] Test and Release
- [ ] User Experience
- [ ] Developer Infrastructure
- [ ] Upgrade
- [ ] Multi Cluster
- [ ] Virtual Machine
- [ ] Control Plane Revisions

Pull request:
fix(networking): support large direct response on gateways
This causes a NACK in Envoy

Fixes #44280 

Patch:
diff --git a/pilot/pkg/networking/core/v1alpha3/gateway.go b/pilot/pkg/networking/core/v1alpha3/gateway.go
index ad9a7dc1e8..cc40f95f13 100644
--- a/pilot/pkg/networking/core/v1alpha3/gateway.go
+++ b/pilot/pkg/networking/core/v1alpha3/gateway.go
@@ -507,10 +507,11 @@ func (configgen *ConfigGeneratorImpl) buildGatewayHTTPRouteConfig(node *model.Pr
 
 	routeCfg := &route.RouteConfiguration{
 		// Retain the routeName as its used by EnvoyFilter patching logic
-		Name:                     routeName,
-		VirtualHosts:             virtualHosts,
-		ValidateClusters:         proto.BoolFalse,
-		IgnorePortInHostMatching: !node.IsProxylessGrpc(),
+		Name:                           routeName,
+		VirtualHosts:                   virtualHosts,
+		ValidateClusters:               proto.BoolFalse,
+		IgnorePortInHostMatching:       !node.IsProxylessGrpc(),
+		MaxDirectResponseBodySizeBytes: istio_route.DefaultMaxDirectResponseBodySizeBytes,
 	}
 
 	return routeCfg
diff --git a/pilot/pkg/networking/core/v1alpha3/httproute.go b/pilot/pkg/networking/core/v1alpha3/httproute.go
index df3d8dc36d..4a7cc31a24 100644
--- a/pilot/pkg/networking/core/v1alpha3/httproute.go
+++ b/pilot/pkg/networking/core/v1alpha3/httproute.go
@@ -26,7 +26,6 @@ import (
 	discovery "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
 	anypb "github.com/golang/protobuf/ptypes/any"
 	"google.golang.org/protobuf/types/known/durationpb"
-	wrappers "google.golang.org/protobuf/types/known/wrapperspb"
 
 	networking "istio.io/api/networking/v1alpha3"
 	"istio.io/istio/pilot/pkg/features"
@@ -205,11 +204,10 @@ func (configgen *ConfigGeneratorImpl) buildSidecarOutboundHTTPRouteConfig(
 	}
 
 	out := &route.RouteConfiguration{
-		Name:             routeName,
-		VirtualHosts:     virtualHosts,
-		ValidateClusters: proto.BoolFalse,
-		// Control plane validates 1mb max size. Set this on data plane too to increase from default of 4k
-		MaxDirectResponseBodySizeBytes: wrappers.UInt32(1024 * 1024),
+		Name:                           routeName,
+		VirtualHosts:                   virtualHosts,
+		ValidateClusters:               proto.BoolFalse,
+		MaxDirectResponseBodySizeBytes: istio_route.DefaultMaxDirectResponseBodySizeBytes,
 	}
 	if features.SidecarIgnorePort {
 		out.IgnorePortInHostMatching = true
diff --git a/pilot/pkg/networking/core/v1alpha3/route/route.go b/pilot/pkg/networking/core/v1alpha3/route/route.go
index 4b26d38b6c..39dccc1b6a 100644
--- a/pilot/pkg/networking/core/v1alpha3/route/route.go
+++ b/pilot/pkg/networking/core/v1alpha3/route/route.go
@@ -63,6 +63,9 @@ const DefaultRouteName = "default"
 
 var Notimeout = durationpb.New(0)
 
+// DefaultMaxDirectResponseBodySizeBytes is 1mb, the same limit the control plane validates via webhook. Set this to increase from envoy default of 4k
+var DefaultMaxDirectResponseBodySizeBytes = wrappers.UInt32(1024 * 1024)
+
 type DestinationHashMap map[*networking.HTTPRouteDestination]*networking.LoadBalancerSettings_ConsistentHashLB
 
 // VirtualHostWrapper is a context-dependent virtual host entry with guarded routes.


Test patch:
diff --git a/pilot/pkg/networking/core/v1alpha3/gateway_test.go b/pilot/pkg/networking/core/v1alpha3/gateway_test.go
index fc308af813..e3d5628421 100644
--- a/pilot/pkg/networking/core/v1alpha3/gateway_test.go
+++ b/pilot/pkg/networking/core/v1alpha3/gateway_test.go
@@ -37,6 +37,7 @@ import (
 	pilot_model "istio.io/istio/pilot/pkg/model"
 	istionetworking "istio.io/istio/pilot/pkg/networking"
 	"istio.io/istio/pilot/pkg/networking/core/v1alpha3/listenertest"
+	istio_route "istio.io/istio/pilot/pkg/networking/core/v1alpha3/route"
 	"istio.io/istio/pilot/pkg/networking/util"
 	"istio.io/istio/pilot/pkg/security/model"
 	xdsfilters "istio.io/istio/pilot/pkg/xds/filters"
@@ -2138,6 +2139,10 @@ func TestGatewayHTTPRouteConfig(t *testing.T) {
 			if r == nil {
 				t.Fatal("got an empty route configuration")
 			}
+			if r.MaxDirectResponseBodySizeBytes != istio_route.DefaultMaxDirectResponseBodySizeBytes {
+				t.Errorf("expected MaxDirectResponseBodySizeBytes %v, got %v",
+					istio_route.DefaultMaxDirectResponseBodySizeBytes, r.MaxDirectResponseBodySizeBytes)
+			}
 			vh := make(map[string][]string)
 			hr := make(map[string]int)
 			for _, h := range r.VirtualHosts {
diff --git a/pilot/test/xdstest/validate.go b/pilot/test/xdstest/validate.go
index 4655350e3c..4b404a2bbb 100644
--- a/pilot/test/xdstest/validate.go
+++ b/pilot/test/xdstest/validate.go
@@ -23,6 +23,7 @@ import (
 	listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
 	route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
 
+	istio_route "istio.io/istio/pilot/pkg/networking/core/v1alpha3/route"
 	xdsfilters "istio.io/istio/pilot/pkg/xds/filters"
 	"istio.io/istio/pkg/util/sets"
 )
@@ -228,6 +229,11 @@ func ValidateRouteConfiguration(t testing.TB, l *route.RouteConfiguration) {
 	if err := l.Validate(); err != nil {
 		t.Errorf("route configuration %v is invalid: %v", l.Name, err)
 	}
+
+	if l.MaxDirectResponseBodySizeBytes.Value != istio_route.DefaultMaxDirectResponseBodySizeBytes.Value {
+		t.Errorf("expected MaxDirectResponseBodySizeBytes %v, got %v",
+			istio_route.DefaultMaxDirectResponseBodySizeBytes, l.MaxDirectResponseBodySizeBytes)
+	}
 	validateRouteConfigurationDomains(t, l)
 }