diff --git a/api/v1alpha1/timeout_types.go b/api/v1alpha1/timeout_types.go index 008582578d1..aab8dd18690 100644 --- a/api/v1alpha1/timeout_types.go +++ b/api/v1alpha1/timeout_types.go @@ -81,4 +81,13 @@ type HTTPClientTimeout struct { // // +optional IdleTimeout *gwapiv1.Duration `json:"idleTimeout,omitempty"` + + // The delayed close timeout is for downstream connections managed by the HTTP connection manager. + // It is defined as a grace period after connection close processing has been locally initiated + // during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy + // from the downstream connection) prior to Envoy closing the socket associated with that + // connection. + //The default timeout is 1000 ms if this option is not specified. + // +optional + DelayedCloseTimeout *gwapiv1.Duration `json:"delayedCloseTimeout,omitempty" yaml:"delayedCloseTimeout,omitempty"` } diff --git a/internal/gatewayapi/clienttrafficpolicy.go b/internal/gatewayapi/clienttrafficpolicy.go index 1c8d0f8af4a..e5f43c86055 100644 --- a/internal/gatewayapi/clienttrafficpolicy.go +++ b/internal/gatewayapi/clienttrafficpolicy.go @@ -603,6 +603,15 @@ func buildClientTimeout(clientTimeout *egv1a1.ClientTimeout) (*ir.ClientTimeout, Duration: d, } } + if clientTimeout.HTTP.DelayedCloseTimeout != nil { + d, err := time.ParseDuration(string(*clientTimeout.HTTP.DelayedCloseTimeout)) + if err != nil { + return nil, fmt.Errorf("invalid HTTP DelayedCloseTimeout value %s", *clientTimeout.HTTP.DelayedCloseTimeout) + } + irHTTPTimeout.DelayedCloseTimeout = &metav1.Duration{ + Duration: d, + } + } irClientTimeout.HTTP = irHTTPTimeout } diff --git a/internal/ir/xds.go b/internal/ir/xds.go index 4db7b8445aa..e739a66cfbe 100644 --- a/internal/ir/xds.go +++ b/internal/ir/xds.go @@ -642,6 +642,13 @@ type HTTPClientTimeout struct { RequestReceivedTimeout *metav1.Duration `json:"requestReceivedTimeout,omitempty" yaml:"requestReceivedTimeout,omitempty"` // IdleTimeout for an HTTP connection. Idle time is defined as a period in which there are no active requests in the connection. IdleTimeout *metav1.Duration `json:"idleTimeout,omitempty" yaml:"idleTimeout,omitempty"` + // The delayed close timeout is for downstream connections managed by the HTTP connection manager. + // It is defined as a grace period after connection close processing has been locally initiated + // during which Envoy will wait for the peer to close (i.e., a TCP FIN/RST is received by Envoy + // from the downstream connection) prior to Envoy closing the socket associated with that + // connection. + //The default timeout is 1000 ms if this option is not specified. + DelayedCloseTimeout *metav1.Duration `json:"delayedCloseTimeout,omitempty" yaml:"delayedCloseTimeout,omitempty"` } // HTTPRoute holds the route information associated with the HTTP Route diff --git a/internal/xds/translator/listener.go b/internal/xds/translator/listener.go index 36cf9a8953b..a6c0187d919 100644 --- a/internal/xds/translator/listener.go +++ b/internal/xds/translator/listener.go @@ -319,6 +319,10 @@ func (t *Translator) addHCMToXDSListener(xdsListener *listenerv3.Listener, irLis if irListener.Timeout.HTTP.IdleTimeout != nil { mgr.CommonHttpProtocolOptions.IdleTimeout = durationpb.New(irListener.Timeout.HTTP.IdleTimeout.Duration) } + + if irListener.Timeout.HTTP.DelayedCloseTimeout != nil { + mgr.DelayedCloseTimeout = durationpb.New(irListener.Timeout.HTTP.DelayedCloseTimeout.Duration) + } } // Add the proxy protocol filter if needed